mirror of
https://github.com/Fishwaldo/OBLFR.git
synced 2025-03-15 11:21:23 +00:00
Few fixes and Port IRQ_Forward to a component (#8)
* Remove a unnecessary delay in the nvkvs * update readme * port IRQ_Forward Code to a component and update d0_lowload to use it * add USB, Ethernet and GPIO for IRQ Forwarding
This commit is contained in:
parent
608b99f21d
commit
e36316fa13
15 changed files with 348 additions and 919 deletions
|
@ -15,10 +15,6 @@ endif()
|
|||
|
||||
include(${SDK_PATH}/cmake/bflbsdk.cmake)
|
||||
|
||||
target_sources(app PRIVATE
|
||||
src/bl808_ipc.c)
|
||||
|
||||
target_compile_options(app PRIVATE -ggdb -Os)
|
||||
sdk_add_include_directories(include)
|
||||
sdk_set_main_file(src/main.c)
|
||||
project(m0_lowload)
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
|
||||
config LL_IRQFWD_SDH
|
||||
bool "Enable IRQ forwarding for SDH"
|
||||
default y
|
||||
|
||||
config LL_IRQFWD_UART2
|
||||
bool "Enable IRQ forwarding for UART2"
|
||||
default y
|
||||
|
||||
config LL_IRQFWD_USB
|
||||
bool "Enable IRQ forwarding for USB"
|
||||
default n
|
||||
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
|
||||
/*
|
||||
* Copyright (C) 2023 Allen Martin <armartin@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __DT_BINDINGS_MAILBOX_BFLB_IPC_H
|
||||
#define __DT_BINDINGS_MAILBOX_BFLB_IPC_H
|
||||
|
||||
/* Peripheral device ID */
|
||||
#define BFLB_IPC_DEVICE_SDHCI 0
|
||||
#define BFLB_IPC_DEVICE_UART2 1
|
||||
#define BLFB_IPC_DEVICE_USB 2
|
||||
|
||||
#endif
|
|
@ -1,7 +1,3 @@
|
|||
|
||||
CONFIG_LL_IRQFWD_SDH=y
|
||||
CONFIG_LL_IRQFWD_UART2=y
|
||||
# CONFIG_LL_IRQFWD_USB is not set
|
||||
CONFIG_PSRAM=y
|
||||
CONFIG_BFLB_CHIP="bl808"
|
||||
CONFIG_BLFB_CPU_ID="m0"
|
||||
CONFIG_COMPONENT_MAILBOX=y
|
||||
CONFIG_COMPONENT_MAILBOX_IRQFWD_SDH=y
|
||||
CONFIG_COMPONENT_MAILBOX_IRQFWD_GPIO=y
|
|
@ -1,738 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file bl808_ipc.c
|
||||
* @version V1.2
|
||||
* @date
|
||||
* @brief This file is the standard driver c file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT(c) 2018 Bouffalo Lab</center></h2>
|
||||
*
|
||||
* 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 "bl808_ipc.h"
|
||||
|
||||
/** @addtogroup BL606P_Peripheral_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup IPC
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup IPC_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
#define IPC_LP_OFFSET_IN_M0 0
|
||||
#define IPC_D0_OFFSET_IN_M0 16
|
||||
|
||||
#define IPC_M0_OFFSET_IN_LP 0
|
||||
#define IPC_D0_OFFSET_IN_LP 16
|
||||
|
||||
#define IPC_M0_OFFSET_IN_D0 0
|
||||
#define IPC_LP_OFFSET_IN_D0 16
|
||||
|
||||
/*@} end of group IPC_Private_Macros */
|
||||
|
||||
/** @defgroup IPC_Private_Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*@} end of group IPC_Private_Types */
|
||||
|
||||
/** @defgroup IPC_Private_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
ipcIntCallback *m0IpcIntCbfArra[GLB_CORE_ID_MAX - 1] = { NULL };
|
||||
ipcIntCallback *lpIpcIntCbfArra[GLB_CORE_ID_MAX - 1] = { NULL };
|
||||
ipcIntCallback *d0IpcIntCbfArra[GLB_CORE_ID_MAX - 1] = { NULL };
|
||||
|
||||
/*@} end of group IPC_Private_Variables */
|
||||
|
||||
/** @defgroup IPC_Global_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*@} end of group IPC_Global_Variables */
|
||||
|
||||
/** @defgroup IPC_Private_Fun_Declaration
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*@} end of group IPC_Private_Fun_Declaration */
|
||||
|
||||
/** @defgroup IPC_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*@} end of group IPC_Private_Functions */
|
||||
|
||||
/** @defgroup IPC_Public_Functions
|
||||
* @{
|
||||
*/
|
||||
#if defined(CPU_M0) || defined(CPU_LP)
|
||||
/****************************************************************************/ /**
|
||||
* @brief M0 IPC interrupt init
|
||||
*
|
||||
* @param onLPTriggerCallBack: Callback when LP trigger
|
||||
*
|
||||
* @param onD0TriggerCallBack: Callback when D0 trigger
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_M0_Init(ipcIntCallback *onLPTriggerCallBack,
|
||||
ipcIntCallback *onD0TriggerCallBack)
|
||||
{
|
||||
m0IpcIntCbfArra[0] = onLPTriggerCallBack;
|
||||
m0IpcIntCbfArra[1] = onD0TriggerCallBack;
|
||||
|
||||
IPC_M0_Int_Unmask_By_Word(0xffffffff);
|
||||
|
||||
#ifndef BFLB_USE_HAL_DRIVER
|
||||
Interrupt_Handler_Register(IPC_M0_IRQn, IPC_M0_IRQHandler);
|
||||
#endif
|
||||
CPU_Interrupt_Enable(IPC_M0_IRQn);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief M0 unmask IPC interrupt
|
||||
*
|
||||
* @param src: M0 IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_M0_Int_Unmask(IPC_Int_Src_Type src)
|
||||
{
|
||||
uint32_t tmpVal = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
CHECK_PARAM(IS_IPC_INT_SRC_TYPE(src));
|
||||
|
||||
tmpVal = (1 << src);
|
||||
|
||||
BL_WR_REG(IPC0_BASE, IPC_CPU0_IPC_IUSR, tmpVal);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief M0 unmask IPC interrupt by word
|
||||
*
|
||||
* @param src: IPC interrupt source in word,every bit is interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_M0_Int_Unmask_By_Word(uint32_t src)
|
||||
{
|
||||
BL_WR_REG(IPC0_BASE, IPC_CPU0_IPC_IUSR, src);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief M0 get IPC interrupt raw status
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return IPC interrupt raw status
|
||||
*
|
||||
*******************************************************************************/
|
||||
uint32_t IPC_M0_Get_Int_Raw_Status(void)
|
||||
{
|
||||
return BL_RD_REG(IPC0_BASE, IPC_CPU0_IPC_IRSRR);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief M0 clear IPC interrupt
|
||||
*
|
||||
* @param src: M0 IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_M0_Clear_Int(IPC_Int_Src_Type src)
|
||||
{
|
||||
uint32_t tmpVal = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
CHECK_PARAM(IS_IPC_INT_SRC_TYPE(src));
|
||||
|
||||
tmpVal = (1 << src);
|
||||
|
||||
BL_WR_REG(IPC0_BASE, IPC_CPU0_IPC_ICR, tmpVal);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief M0 clear IPC interrupt by word
|
||||
*
|
||||
* @param src: IPC interrupt source in word,every bit is interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_M0_Clear_Int_By_Word(uint32_t src)
|
||||
{
|
||||
BL_WR_REG(IPC0_BASE, IPC_CPU0_IPC_ICR, src);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief CPUx trigger IPC interrupt to M0
|
||||
*
|
||||
* @param src: IPC interrupt source
|
||||
*
|
||||
* @param cpuxOffset: CPU interrupt offset
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_CPUx_Trigger_M0(IPC_Grp_Int_Src_Type src, uint8_t cpuxOffset)
|
||||
{
|
||||
uint32_t tmpVal = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
CHECK_PARAM(IS_IPC_Grp_Int_Src_Type(src));
|
||||
|
||||
tmpVal = (1 << (src + cpuxOffset));
|
||||
|
||||
BL_WR_REG(IPC0_BASE, IPC_CPU1_IPC_ISWR, tmpVal);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief LP trigger IPC interrupt to M0
|
||||
*
|
||||
* @param src: LP IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_LP_Trigger_M0(IPC_Grp_Int_Src_Type src)
|
||||
{
|
||||
IPC_CPUx_Trigger_M0(src, IPC_LP_OFFSET_IN_M0);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 trigger IPC interrupt to M0
|
||||
*
|
||||
* @param src: D0 IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_D0_Trigger_M0(IPC_Grp_Int_Src_Type src)
|
||||
{
|
||||
IPC_CPUx_Trigger_M0(src, IPC_D0_OFFSET_IN_M0);
|
||||
}
|
||||
|
||||
#if defined(CPU_M0) || defined(CPU_LP)
|
||||
/****************************************************************************/ /**
|
||||
* @brief LP IPC interrupt init
|
||||
*
|
||||
* @param onM0TriggerCallBack: Callback when M0 trigger
|
||||
*
|
||||
* @param onD0TriggerCallBack: Callback when D0 trigger
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_LP_Init(ipcIntCallback *onM0TriggerCallBack,
|
||||
ipcIntCallback *onD0TriggerCallBack)
|
||||
{
|
||||
lpIpcIntCbfArra[0] = onM0TriggerCallBack;
|
||||
lpIpcIntCbfArra[1] = onD0TriggerCallBack;
|
||||
|
||||
IPC_LP_Int_Unmask_By_Word(0xffffffff);
|
||||
|
||||
#ifndef BFLB_USE_HAL_DRIVER
|
||||
Interrupt_Handler_Register(IPC_LP_IRQn, IPC_LP_IRQHandler);
|
||||
#endif
|
||||
CPU_Interrupt_Enable(IPC_LP_IRQn);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief LP unmask IPC interrupt
|
||||
*
|
||||
* @param src: LP IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_LP_Int_Unmask(IPC_Int_Src_Type src)
|
||||
{
|
||||
uint32_t tmpVal = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
CHECK_PARAM(IS_IPC_INT_SRC_TYPE(src));
|
||||
|
||||
tmpVal = (1 << src);
|
||||
|
||||
BL_WR_REG(IPC1_BASE, IPC_CPU0_IPC_IUSR, tmpVal);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief LP unmask IPC interrupt by word
|
||||
*
|
||||
* @param src: IPC interrupt source in word,every bit is interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_LP_Int_Unmask_By_Word(uint32_t src)
|
||||
{
|
||||
BL_WR_REG(IPC1_BASE, IPC_CPU0_IPC_IUSR, src);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief LP get IPC interrupt raw status
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return IPC interrupt raw status
|
||||
*
|
||||
*******************************************************************************/
|
||||
uint32_t IPC_LP_Get_Int_Raw_Status(void)
|
||||
{
|
||||
return BL_RD_REG(IPC1_BASE, IPC_CPU0_IPC_IRSRR);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief LP clear IPC interrupt
|
||||
*
|
||||
* @param src: LP IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_LP_Clear_Int(IPC_Int_Src_Type src)
|
||||
{
|
||||
uint32_t tmpVal = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
CHECK_PARAM(IS_IPC_INT_SRC_TYPE(src));
|
||||
|
||||
tmpVal = (1 << src);
|
||||
|
||||
BL_WR_REG(IPC1_BASE, IPC_CPU0_IPC_ICR, tmpVal);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief LP clear IPC interrupt by word
|
||||
*
|
||||
* @param src: IPC interrupt source in word,every bit is interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_LP_Clear_Int_By_Word(uint32_t src)
|
||||
{
|
||||
BL_WR_REG(IPC1_BASE, IPC_CPU0_IPC_ICR, src);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief CPUx trigger IPC interrupt to LP
|
||||
*
|
||||
* @param src: IPC interrupt source
|
||||
*
|
||||
* @param cpuxOffset: CPU interrupt offset
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_CPUx_Trigger_LP(IPC_Grp_Int_Src_Type src, uint8_t cpuxOffset)
|
||||
{
|
||||
uint32_t tmpVal = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
CHECK_PARAM(IS_IPC_Grp_Int_Src_Type(src));
|
||||
|
||||
tmpVal = (1 << (src + cpuxOffset));
|
||||
|
||||
BL_WR_REG(IPC1_BASE, IPC_CPU1_IPC_ISWR, tmpVal);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief M0 trigger IPC interrupt to LP
|
||||
*
|
||||
* @param src: M0 IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_M0_Trigger_LP(IPC_Grp_Int_Src_Type src)
|
||||
{
|
||||
IPC_CPUx_Trigger_LP(src, IPC_M0_OFFSET_IN_LP);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 trigger IPC interrupt to LP
|
||||
*
|
||||
* @param src: D0 IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_D0_Trigger_LP(IPC_Grp_Int_Src_Type src)
|
||||
{
|
||||
IPC_CPUx_Trigger_LP(src, IPC_D0_OFFSET_IN_LP);
|
||||
}
|
||||
|
||||
#if defined(CPU_D0) || defined(CPU_D1)
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 IPC interrupt init
|
||||
*
|
||||
* @param onM0TriggerCallBack: Callback when M0 trigger
|
||||
*
|
||||
* @param onLPTriggerCallBack: Callback when LP trigger
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_D0_Init(ipcIntCallback *onM0TriggerCallBack,
|
||||
ipcIntCallback *onLPTriggerCallBack)
|
||||
{
|
||||
d0IpcIntCbfArra[0] = onM0TriggerCallBack;
|
||||
d0IpcIntCbfArra[1] = onLPTriggerCallBack;
|
||||
|
||||
IPC_D0_Int_Unmask_By_Word(0xffffffff);
|
||||
|
||||
#ifndef BFLB_USE_HAL_DRIVER
|
||||
Interrupt_Handler_Register(IPC_D0_IRQn, IPC_D0_IRQHandler);
|
||||
#endif
|
||||
CPU_Interrupt_Enable(IPC_D0_IRQn);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 unmask IPC interrupt
|
||||
*
|
||||
* @param src: D0 IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_D0_Int_Unmask(IPC_Int_Src_Type src)
|
||||
{
|
||||
uint32_t tmpVal = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
CHECK_PARAM(IS_IPC_INT_SRC_TYPE(src));
|
||||
|
||||
tmpVal = (1 << src);
|
||||
|
||||
BL_WR_REG(IPC2_BASE, IPC_CPU0_IPC_IUSR, tmpVal);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 unmask IPC interrupt by word
|
||||
*
|
||||
* @param src: D0 IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_D0_Int_Unmask_By_Word(uint32_t src)
|
||||
{
|
||||
BL_WR_REG(IPC2_BASE, IPC_CPU0_IPC_IUSR, src);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 get IPC interrupt raw status
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return IPC interrupt raw status
|
||||
*
|
||||
*******************************************************************************/
|
||||
uint32_t IPC_D0_Get_Int_Raw_Status(void)
|
||||
{
|
||||
return BL_RD_REG(IPC2_BASE, IPC_CPU0_IPC_IRSRR);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 clear IPC interrupt
|
||||
*
|
||||
* @param src: D0 IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_D0_Clear_Int(IPC_Int_Src_Type src)
|
||||
{
|
||||
uint32_t tmpVal = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
CHECK_PARAM(IS_IPC_INT_SRC_TYPE(src));
|
||||
|
||||
tmpVal = (1 << src);
|
||||
|
||||
BL_WR_REG(IPC2_BASE, IPC_CPU0_IPC_ICR, tmpVal);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 clear IPC interrupt by word
|
||||
*
|
||||
* @param src: IPC interrupt source in word,every bit is interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_D0_Clear_Int_By_Word(uint32_t src)
|
||||
{
|
||||
BL_WR_REG(IPC2_BASE, IPC_CPU0_IPC_ICR, src);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief CPUx trigger IPC interrupt to D0
|
||||
*
|
||||
* @param src: IPC interrupt source
|
||||
*
|
||||
* @param cpuxOffset: CPU interrupt offset
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_CPUx_Trigger_D0(IPC_Grp_Int_Src_Type src, uint8_t cpuxOffset)
|
||||
{
|
||||
uint32_t tmpVal = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
CHECK_PARAM(IS_IPC_Grp_Int_Src_Type(src));
|
||||
|
||||
tmpVal = (1 << (src + cpuxOffset));
|
||||
|
||||
BL_WR_REG(IPC2_BASE, IPC_CPU1_IPC_ISWR, tmpVal);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief M0 trigger IPC interrupt to D0
|
||||
*
|
||||
* @param src: M0 IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_M0_Trigger_D0(IPC_Grp_Int_Src_Type src)
|
||||
{
|
||||
IPC_CPUx_Trigger_D0(src, IPC_M0_OFFSET_IN_D0);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief LP trigger IPC interrupt to D0
|
||||
*
|
||||
* @param src: LP IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_LP_Trigger_D0(IPC_Grp_Int_Src_Type src)
|
||||
{
|
||||
IPC_CPUx_Trigger_D0(src, IPC_LP_OFFSET_IN_D0);
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief M0 trigger IPC interrupt to CPUx
|
||||
*
|
||||
* @param tgtCPU: Target CPU
|
||||
*
|
||||
* @param src: IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_M0_Trigger_CPUx(GLB_CORE_ID_Type tgtCPU, IPC_Grp_Int_Src_Type src)
|
||||
{
|
||||
switch (tgtCPU) {
|
||||
case GLB_CORE_ID_LP:
|
||||
IPC_M0_Trigger_LP(src);
|
||||
break;
|
||||
case GLB_CORE_ID_D0:
|
||||
IPC_M0_Trigger_D0(src);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief LP trigger IPC interrupt to CPUx
|
||||
*
|
||||
* @param tgtCPU: Target CPU
|
||||
*
|
||||
* @param src: IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_LP_Trigger_CPUx(GLB_CORE_ID_Type tgtCPU, IPC_Grp_Int_Src_Type src)
|
||||
{
|
||||
switch (tgtCPU) {
|
||||
case GLB_CORE_ID_M0:
|
||||
IPC_LP_Trigger_M0(src);
|
||||
break;
|
||||
case GLB_CORE_ID_D0:
|
||||
IPC_LP_Trigger_D0(src);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 trigger IPC interrupt to CPUx
|
||||
*
|
||||
* @param tgtCPU: Target CPU
|
||||
*
|
||||
* @param src: IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_D0_Trigger_CPUx(GLB_CORE_ID_Type tgtCPU, IPC_Grp_Int_Src_Type src)
|
||||
{
|
||||
switch (tgtCPU) {
|
||||
case GLB_CORE_ID_M0:
|
||||
IPC_D0_Trigger_M0(src);
|
||||
break;
|
||||
case GLB_CORE_ID_LP:
|
||||
IPC_D0_Trigger_LP(src);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 trigger IPC interrupt to D1
|
||||
*
|
||||
* @param src: D0 IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_Trigger_Target_CPU(GLB_CORE_ID_Type tgtCPU, IPC_Grp_Int_Src_Type src)
|
||||
{
|
||||
GLB_CORE_ID_Type localCPU = GLB_Get_Core_Type();
|
||||
|
||||
switch (localCPU) {
|
||||
case GLB_CORE_ID_M0:
|
||||
IPC_M0_Trigger_CPUx(tgtCPU, src);
|
||||
break;
|
||||
case GLB_CORE_ID_LP:
|
||||
IPC_LP_Trigger_CPUx(tgtCPU, src);
|
||||
break;
|
||||
case GLB_CORE_ID_D0:
|
||||
IPC_D0_Trigger_CPUx(tgtCPU, src);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 trigger IPC interrupt to D1
|
||||
*
|
||||
* @param src: D0 IPC interrupt source
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
void IPC_Common_Interrupt_Handler(uint32_t irqStatus, ipcIntCallback *callBack[GLB_CORE_ID_MAX - 1])
|
||||
{
|
||||
uint32_t tmp;
|
||||
uint32_t grp = 0;
|
||||
|
||||
for (grp = 0; grp < GLB_CORE_ID_MAX - 1; grp++) {
|
||||
tmp = (irqStatus >> (16 * grp)) & 0xffff;
|
||||
if (tmp != 0) {
|
||||
if (callBack[grp] != NULL) {
|
||||
callBack[grp](tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief M0 IPC IRQ handler
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
#ifndef BFLB_USE_HAL_DRIVER
|
||||
void IPC_M0_IRQHandler(void)
|
||||
{
|
||||
uint32_t irqStatus;
|
||||
MSG("%s: wrong handler!!\n", __func__);
|
||||
irqStatus = IPC_M0_Get_Int_Raw_Status();
|
||||
IPC_Common_Interrupt_Handler(irqStatus, m0IpcIntCbfArra);
|
||||
IPC_M0_Clear_Int_By_Word(irqStatus);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief LP IPC IRQ handler
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
#ifndef BFLB_USE_HAL_DRIVER
|
||||
void IPC_LP_IRQHandler(void)
|
||||
{
|
||||
uint32_t irqStatus;
|
||||
irqStatus = IPC_LP_Get_Int_Raw_Status();
|
||||
IPC_Common_Interrupt_Handler(irqStatus, lpIpcIntCbfArra);
|
||||
IPC_LP_Clear_Int_By_Word(irqStatus);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************/ /**
|
||||
* @brief D0 IPC IRQ handler
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
*******************************************************************************/
|
||||
#ifndef BFLB_USE_HAL_DRIVER
|
||||
void IPC_D0_IRQHandler(void)
|
||||
{
|
||||
uint32_t irqStatus;
|
||||
irqStatus = IPC_D0_Get_Int_Raw_Status();
|
||||
IPC_Common_Interrupt_Handler(irqStatus, d0IpcIntCbfArra);
|
||||
IPC_D0_Clear_Int_By_Word(irqStatus);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*@} end of group IPC_Public_Functions */
|
||||
|
||||
/*@} end of group IPC */
|
||||
|
||||
/*@} end of group BL606P_Peripheral_Driver */
|
|
@ -21,158 +21,32 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define DBG_TAG "MAIN"
|
||||
|
||||
#include <bl808_common.h>
|
||||
#include <bflb_irq.h>
|
||||
#include <bflb_clock.h>
|
||||
#include <bflb_gpio.h>
|
||||
#include <bl808_ipc.h>
|
||||
#include <ipc_reg.h>
|
||||
#include <sdh_reg.h>
|
||||
#include <log.h>
|
||||
#include <stdio.h>
|
||||
#include <board.h>
|
||||
#include "irq-forward.h"
|
||||
#include <bflb_mtimer.h>
|
||||
#include "oblfr_mailbox.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#define DBG_TAG "MAIN"
|
||||
#include <log.h>
|
||||
|
||||
static uint32_t ipc_irqs[32] = {
|
||||
#ifdef CONFIG_LL_IRQFWD_SDH
|
||||
[BFLB_IPC_DEVICE_SDHCI] = SDH_IRQn,
|
||||
#endif
|
||||
#ifdef CONFIG_LL_IRQFWD_UART2
|
||||
[BFLB_IPC_DEVICE_UART2] = UART2_IRQn,
|
||||
#endif
|
||||
#ifdef CONFIG_LL_IRQFWD_USB
|
||||
[BLFB_IPC_DEVICE_USB] = USB_IRQn,
|
||||
#endif
|
||||
0,
|
||||
};
|
||||
|
||||
static void Send_IPC_IRQ(int device)
|
||||
{
|
||||
bflb_irq_disable(ipc_irqs[device]);
|
||||
BL_WR_REG(IPC2_BASE, IPC_CPU1_IPC_ISWR, (1 << device));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LL_IRQFWD_SDH
|
||||
void SDH_MMC1_IRQHandler(int irq, void *arg)
|
||||
{
|
||||
LOG_D("Got SDH IRQ\r\n");
|
||||
Send_IPC_IRQ(BFLB_IPC_DEVICE_SDHCI);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LL_IRQFWD_UART2
|
||||
void UART2_IRQHandler(int irq, void *arg)
|
||||
{
|
||||
LOG_D("Got UART IRQ\r\n");
|
||||
Send_IPC_IRQ(BFLB_IPC_DEVICE_UART2);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LL_IRQFWD_USB
|
||||
void USB_IRQHandler(int irq, void *arg)
|
||||
{
|
||||
LOG_D("Got USB IRQ\r\n");
|
||||
Send_IPC_IRQ(BLFB_IPC_DEVICE_USB);
|
||||
}
|
||||
#endif
|
||||
|
||||
void IPC_M0_IRQHandler(int irq, void *arg)
|
||||
{
|
||||
int i;
|
||||
uint32_t irqStatus = IPC_M0_Get_Int_Raw_Status();
|
||||
|
||||
for (i = 0; i < sizeof(irqStatus) * 8; i++)
|
||||
{
|
||||
if (irqStatus & (1 << i)) {
|
||||
LOG_D("Got IPC EOI for device %d\r\n");
|
||||
bflb_irq_enable(ipc_irqs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
BL_WR_REG(IPC0_BASE, IPC_CPU0_IPC_ICR, irqStatus);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LL_IRQFWD_SDH
|
||||
int setup_sdh_peripheral() {
|
||||
LOG_D("setting up SDH peripheral\r\n");
|
||||
struct bflb_device_s *gpio;
|
||||
|
||||
gpio = bflb_device_get_by_name("gpio");
|
||||
bflb_gpio_init(gpio, GPIO_PIN_0, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_1, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_2, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_3, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_4, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_5, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
|
||||
|
||||
PERIPHERAL_CLOCK_SDH_ENABLE();
|
||||
// uint32_t tmp_val;
|
||||
// tmp_val = BL_RD_REG(PDS_BASE, PDS_CTL5);
|
||||
// uint32_t tmp_val2 = BL_GET_REG_BITS_VAL(tmp_val, PDS_CR_PDS_GPIO_KEEP_EN);
|
||||
// tmp_val2 &= ~(1 << 0);
|
||||
// tmp_val = BL_SET_REG_BITS_VAL(tmp_val, PDS_CR_PDS_GPIO_KEEP_EN, tmp_val2);
|
||||
// BL_WR_REG(PDS_BASE, PDS_CTL5, tmp_val);
|
||||
// GLB_AHB_MCU_Software_Reset(GLB_AHB_MCU_SW_SDH);
|
||||
LOG_D("SDH peripheral clock: %d\r\n", bflb_clk_get_peripheral_clock(BFLB_DEVICE_TYPE_SDH, 0)/1000000);
|
||||
return SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(void)
|
||||
{
|
||||
board_init();
|
||||
|
||||
LOG_I("M0 CPU start...\r\n");
|
||||
LOG_I("Starting Mailbox Handlers\r\n");
|
||||
|
||||
LOG_I("registering IPC interrupt handler\r\n");
|
||||
|
||||
bflb_irq_attach(IPC_M0_IRQn, IPC_M0_IRQHandler, NULL);
|
||||
IPC_M0_Int_Unmask_By_Word(0xffffffff);
|
||||
bflb_irq_enable(IPC_M0_IRQn);
|
||||
|
||||
#ifdef CONFIG_LL_IRQFWD_SDH
|
||||
LOG_I("registering SDH interrupt handler\r\n");
|
||||
|
||||
bflb_irq_attach(SDH_IRQn, SDH_MMC1_IRQHandler, NULL);
|
||||
bflb_irq_enable(SDH_IRQn);
|
||||
if (setup_sdh_peripheral() != SUCCESS) {
|
||||
LOG_E("Failed to setup SDH peripheral\r\n");
|
||||
if (oblfr_mailbox_init() != OBLFR_OK) {
|
||||
LOG_E("oblfr_mailbox_init failed\r\n");
|
||||
while (1) {
|
||||
;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LL_IRQFWD_UART2
|
||||
LOG_I("registering UART2 interrupt handler\r\n");
|
||||
|
||||
bflb_irq_attach(UART2_IRQn, UART2_IRQHandler, NULL);
|
||||
bflb_irq_enable(UART2_IRQn);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LL_IRQFWD_USB
|
||||
LOG_I("registering USB interrupt handler\r\n");
|
||||
|
||||
bflb_irq_attach(USB_IRQn, UART2_IRQHandler, NULL);
|
||||
bflb_irq_enable(USB_IRQn);
|
||||
#endif
|
||||
|
||||
LOG_I("Running...\r\n");
|
||||
while (1)
|
||||
{
|
||||
{
|
||||
static int x = 0;
|
||||
if ((x++ % 999999999) == 0)
|
||||
{
|
||||
{
|
||||
// dump_ipc(IPC0_BASE);
|
||||
// dump_ipc(IPC1_BASE);
|
||||
LOG_I(".\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
int dummy;
|
||||
/* In lieu of a halt instruction, induce a long-latency stall. */
|
||||
__asm__ __volatile__("div %0, %0, zero"
|
||||
: "=r"(dummy));
|
||||
oblfr_mailbox_dump();
|
||||
bflb_mtimer_delay_ms(5000);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ if(BOARD_DIR)
|
|||
endif()
|
||||
|
||||
find_package(bouffalo_sdk REQUIRED HINTS $ENV{BL_SDK_BASE})
|
||||
include(${SDK_PATH}/cmake/sdk.cmake)
|
||||
include(${SDK_PATH}/cmake/kconfig.cmake)
|
||||
|
||||
add_subdirectory(${SDK_PATH}/bsp/common/ bsp_common)
|
||||
|
|
6
cmake/sdk.cmake
Normal file
6
cmake/sdk.cmake
Normal file
|
@ -0,0 +1,6 @@
|
|||
cmake_minimum_required(VERSION 3.15)
|
||||
function(sdk_add_include_directories_ifndef feature)
|
||||
if(NOT DEFINED ${feature})
|
||||
sdk_add_include_directories(${ARGN})
|
||||
endif()
|
||||
endfunction()
|
|
@ -1,5 +1,9 @@
|
|||
sdk_add_subdirectory_ifdef(CONFIG_COMPONENT_SYSTEM oblfr)
|
||||
#if we do not include the SYSTEM component, we need to at add the include directory */
|
||||
sdk_add_include_directories_ifndef(CONFIG_COMPONENT_SYSTEM_OBLFR oblfr/include)
|
||||
|
||||
sdk_add_subdirectory_ifdef(CONFIG_COMPONENT_BUTTON button)
|
||||
sdk_add_subdirectory_ifdef(CONFIG_COMPONENT_STATUS_LED indicator)
|
||||
sdk_add_subdirectory_ifdef(CONFIG_COMPONENT_TIMER timer)
|
||||
sdk_add_subdirectory_ifdef(CONFIG_COMPONENT_NVKVS nvkvs)
|
||||
sdk_add_subdirectory_ifdef(CONFIG_COMPONENT_NVKVS nvkvs)
|
||||
sdk_add_subdirectory_ifdef(CONFIG_COMPONENT_MAILBOX mailbox)
|
4
components/mailbox/CMakeLists.txt
Normal file
4
components/mailbox/CMakeLists.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
sdk_generate_library(oblfr_mailbox)
|
||||
sdk_add_include_directories(include)
|
||||
sdk_library_add_sources(${CMAKE_CURRENT_SOURCE_DIR}/src/oblfr_mailbox.c)
|
||||
|
44
components/mailbox/Kconfig
Normal file
44
components/mailbox/Kconfig
Normal file
|
@ -0,0 +1,44 @@
|
|||
config COMPONENT_MAILBOX
|
||||
bool "Mailbox Support for Linux"
|
||||
default y
|
||||
help
|
||||
Mailbox Component forwards IRQ's to the D0 core for Linux
|
||||
support. Enable this component if you are running linux on
|
||||
the D0 core.
|
||||
|
||||
Please see the README.md file in the Mailbox component directory
|
||||
for more information
|
||||
|
||||
menu "Mailbox Configuration"
|
||||
visible if COMPONENT_MAILBOX
|
||||
config COMPONENT_MAILBOX_IRQFWD_SDH
|
||||
bool "Enable IRQ forwarding for SDH"
|
||||
default y
|
||||
|
||||
config COMPONENT_MAILBOX_IRQFWD_UART2
|
||||
bool "Enable IRQ forwarding for UART2"
|
||||
default n
|
||||
help
|
||||
Enable if you wish to use UART2 for linux
|
||||
|
||||
config COMPONENT_MAILBOX_IRQFWD_USB
|
||||
bool "Enable IRQ forwarding for USB"
|
||||
default n
|
||||
help
|
||||
Curently disabled as USB is not working
|
||||
|
||||
config COMPONENT_MAILBOX_IRQFWD_GPIO
|
||||
bool "Enable IRQ forwarding for GPIO"
|
||||
default y
|
||||
help
|
||||
enable if you need Interupt Support for GPIO on Linux
|
||||
|
||||
config COMPONENT_MAILBOX_IRQFWD_EMAC
|
||||
bool "Enable IRQ forwarding for Ethernet"
|
||||
default y if BOARD_M1SDOCK
|
||||
default n
|
||||
help
|
||||
enable if you need Interupt Support for Ethernet on Linux
|
||||
Currently supported on M1SDock to to vddio2 being
|
||||
wrong voltage for OX64
|
||||
endmenu
|
30
components/mailbox/README.md
Normal file
30
components/mailbox/README.md
Normal file
|
@ -0,0 +1,30 @@
|
|||
## Mailbox
|
||||
This components supports running linux on the D0 core
|
||||
Include this in your M0 firmware to allow linux to continue to operate
|
||||
|
||||
## Description
|
||||
Several Peripherals of the BL808 only have their IRQ attached to the M0 core.
|
||||
This component "forwards" these IRQs to the M0 core to allow Linux to operate.
|
||||
|
||||
This component also includes support for the bl808-ipc driver on linux, which is
|
||||
mailbox driver. It allows Linux running on the D0 core to send interupts to the M0 core.
|
||||
|
||||
## Peripherals Forwarded
|
||||
The following Peripherals can be forwarded to the M0 core. (You can
|
||||
change this via ```make config```) under your project configuartion, but be aware,
|
||||
some peripherals might not work in linux if you disable them here.
|
||||
|
||||
* SD Card Support (Mandatory to have your rootfs on the SD card)
|
||||
* UART2 of the M0 core forwarded to Linux
|
||||
* USB Support
|
||||
* GPIO Pins (See below for caveats)
|
||||
* Ethernet
|
||||
|
||||
## GPIO Interupt Support
|
||||
To be documented.
|
||||
|
||||
## Ethernet Support
|
||||
Enabling Ethernet Support also initilizes the Ethernet Peripheral via the M0 core.
|
||||
|
||||
## SDHCI Support
|
||||
Enabling SD Card Support also initializes the SDHCI Peripheral via the M0 core.
|
23
components/mailbox/include/oblfr_mailbox.h
Normal file
23
components/mailbox/include/oblfr_mailbox.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef __OBLFR_MAILBOX_H__
|
||||
#define __OBLFR_MAILBOX_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "oblfr_common.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/* Peripheral device ID */
|
||||
#define BFLB_IPC_DEVICE_SDHCI 0
|
||||
#define BFLB_IPC_DEVICE_UART2 1
|
||||
#define BLFB_IPC_DEVICE_USB 2
|
||||
#define BFLB_IPC_DEVICE_EMAC 3
|
||||
#define BFLB_IPC_DEVICE_GPIO 4
|
||||
#define BFLB_IPC_DEVICE_MAILBOX 5
|
||||
|
||||
|
||||
oblfr_err_t oblfr_mailbox_init(void);
|
||||
|
||||
oblfr_err_t oblfr_mailbox_dump();
|
||||
|
||||
#endif
|
217
components/mailbox/src/oblfr_mailbox.c
Normal file
217
components/mailbox/src/oblfr_mailbox.c
Normal file
|
@ -0,0 +1,217 @@
|
|||
// Copyright 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <board.h>
|
||||
#include <bl808.h>
|
||||
#include <bl808_common.h>
|
||||
#include <bl808_glb.h>
|
||||
#include <ipc_reg.h>
|
||||
#include <bflb_clock.h>
|
||||
#include <bflb_gpio.h>
|
||||
#include "oblfr_mailbox.h"
|
||||
#define DBG_TAG "MBOX"
|
||||
#include "log.h"
|
||||
|
||||
#ifndef CONFIG_CHIP_BL808
|
||||
#error "This component is only for BL808"
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
char name[16];
|
||||
uint32_t irq;
|
||||
uint32_t count;
|
||||
void (*handler)(int irq, void *arg);
|
||||
} mbox_irq_t;
|
||||
|
||||
static void Send_IPC_IRQ(int device);
|
||||
|
||||
#ifdef CONFIG_COMPONENT_MAILBOX_IRQFWD_SDH
|
||||
static void SDHCI_IRQHandler(int irq, void *arg)
|
||||
{
|
||||
LOG_T("Got SDH IRQ\r\n");
|
||||
Send_IPC_IRQ(BFLB_IPC_DEVICE_SDHCI);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_COMPONENT_MAILBOX_IRQFWD_UART2
|
||||
static void UART2_IRQHandler(int irq, void *arg)
|
||||
{
|
||||
LOG_T("Got UART IRQ\r\n");
|
||||
Send_IPC_IRQ(BFLB_IPC_DEVICE_UART2);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_COMPONENT_MAILBOX_IRQFWD_USB
|
||||
static void USB_IRQHandler(int irq, void *arg)
|
||||
{
|
||||
LOG_T("Got USB IRQ\r\n");
|
||||
Send_IPC_IRQ(BLFB_IPC_DEVICE_USB);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_COMPONENT_MAILBOX_IRQFWD_EMAC
|
||||
static void EMAC_IRQHandler(int irq, void *arg)
|
||||
{
|
||||
LOG_T("Got EMAC IRQ\r\n");
|
||||
Send_IPC_IRQ(BFLB_IPC_DEVICE_EMAC);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_COMPONENT_MAILBOX_IRQFWD_GPIO
|
||||
static void GPIO_IRQHandler(int irq, void *arg)
|
||||
{
|
||||
LOG_T("Got GPIO IRQ\r\n");
|
||||
Send_IPC_IRQ(BFLB_IPC_DEVICE_GPIO);
|
||||
}
|
||||
#endif
|
||||
|
||||
static mbox_irq_t ipc_irqs[32] = {
|
||||
#ifdef CONFIG_COMPONENT_MAILBOX_IRQFWD_SDH
|
||||
[BFLB_IPC_DEVICE_SDHCI] = { "SDH", SDH_IRQn, 0, SDHCI_IRQHandler},
|
||||
#endif
|
||||
#ifdef CONFIG_COMPONENT_MAILBOX_IRQFWD_UART2
|
||||
[BFLB_IPC_DEVICE_UART2] = { "UART2", UART2_IRQn, 0, UART2_IRQHandler},
|
||||
#endif
|
||||
#ifdef CONFIG_COMPONENT_MAILBOX_IRQFWD_USB
|
||||
[BLFB_IPC_DEVICE_USB] = { "USB", USB_IRQn, 0, USB_IRQHandler},
|
||||
#endif
|
||||
#ifdef CONFIG_COMPONENT_MAILBOX_IRQFWD_EMAC
|
||||
[BFLB_IPC_DEVICE_EMAC] = { "EMAC", EMAC_IRQn, 0, EMAC_IRQHandler},
|
||||
#endif
|
||||
#ifdef CONFIG_COMPONENT_MAILBOX_IRQFWD_GPIO
|
||||
[BFLB_IPC_DEVICE_GPIO] = { "GPIO", GPIO_INT0_IRQn, 0, GPIO_IRQHandler},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
static void Send_IPC_IRQ(int device)
|
||||
{
|
||||
if (ipc_irqs[device].irq == 0) {
|
||||
LOG_E("Invalid IPC IRQ %d\r\n", device);
|
||||
return;
|
||||
}
|
||||
bflb_irq_disable(ipc_irqs[device].irq);
|
||||
BL_WR_REG(IPC2_BASE, IPC_CPU1_IPC_ISWR, (1 << device));
|
||||
ipc_irqs[device].count++;
|
||||
}
|
||||
|
||||
void IPC_M0_IRQHandler(int irq, void *arg)
|
||||
{
|
||||
int i;
|
||||
uint32_t irqStatus = BL_RD_REG(IPC0_BASE, IPC_CPU0_IPC_IRSRR);
|
||||
for (i = 0; i < sizeof(irqStatus) * 8; i++)
|
||||
{
|
||||
if (irqStatus & (1 << i)) {
|
||||
if (i == BFLB_IPC_DEVICE_MAILBOX) {
|
||||
LOG_I("Got Mailbox IRQ\r\n");
|
||||
} else {
|
||||
if (ipc_irqs[i].irq == 0) {
|
||||
LOG_W("Got IPC IRQ for unknown peripheral %d\r\n", i);
|
||||
} else {
|
||||
LOG_T("Got IPC EOI for Peripheral %s (%d - %d)\r\n", ipc_irqs[i].name, irqStatus, ipc_irqs[i].irq);
|
||||
//assert(irqStatus == ipc_irqs[irqStatus].irq);
|
||||
bflb_irq_enable(ipc_irqs[i].irq);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BL_WR_REG(IPC0_BASE, IPC_CPU0_IPC_ICR, irqStatus);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPONENT_MAILBOX_IRQFWD_SDH
|
||||
oblfr_err_t setup_sdh_peripheral() {
|
||||
LOG_D("setting up SDH peripheral\r\n");
|
||||
struct bflb_device_s *gpio;
|
||||
|
||||
gpio = bflb_device_get_by_name("gpio");
|
||||
bflb_gpio_init(gpio, GPIO_PIN_0, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_1, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_2, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_3, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_4, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
|
||||
bflb_gpio_init(gpio, GPIO_PIN_5, GPIO_FUNC_SDH | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
|
||||
|
||||
PERIPHERAL_CLOCK_SDH_ENABLE();
|
||||
LOG_D("SDH peripheral clock: %d\r\n", bflb_clk_get_peripheral_clock(BFLB_DEVICE_TYPE_SDH, 0)/1000000);
|
||||
return OBLFR_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef COMPONENT_MAILBOX_IRQFWD_EMAC
|
||||
static oblfr_err_t setup_emac_peripheral(void)
|
||||
{
|
||||
GLB_GPIO_Cfg_Type gpio_cfg;
|
||||
int pin;
|
||||
|
||||
PERIPHERAL_CLOCK_EMAC_ENABLE();
|
||||
|
||||
struct bflb_device_s *gpio = bflb_device_get_by_name("gpio");
|
||||
for (pin = GLB_GPIO_PIN_24; pin <= GLB_GPIO_PIN_33; pin++) {
|
||||
bflb_gpio_init(gpio, pin, GPIO_FUNC_EMAC | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_2);
|
||||
}
|
||||
return OBLFR_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
oblfr_err_t oblfr_mailbox_init()
|
||||
{
|
||||
int i;
|
||||
|
||||
/* setup the IPC Interupt */
|
||||
bflb_irq_attach(IPC_M0_IRQn, IPC_M0_IRQHandler, NULL);
|
||||
BL_WR_REG(IPC0_BASE, IPC_CPU0_IPC_IUSR, 0xffffffff);
|
||||
bflb_irq_enable(IPC_M0_IRQn);
|
||||
|
||||
/* register our Interupt Handlers to forward over */
|
||||
|
||||
for (i = 0; i < sizeof(ipc_irqs) / sizeof(ipc_irqs[0]); i++) {
|
||||
if (ipc_irqs[i].irq != 0) {
|
||||
LOG_I("Forwarding Interupt %s (%d) to D0 (%p)\r\n", ipc_irqs[i].name, ipc_irqs[i].irq, ipc_irqs[i].handler);
|
||||
bflb_irq_attach(ipc_irqs[i].irq, ipc_irqs[i].handler, NULL);
|
||||
bflb_irq_enable(ipc_irqs[i].irq);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPONENT_MAILBOX_IRQFWD_SDH
|
||||
if (setup_sdh_peripheral() != SUCCESS) {
|
||||
LOG_E("Failed to setup SDH peripheral\r\n");
|
||||
return OBLFR_ERR_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef COMPONENT_MAILBOX_IRQFWD_EMAC
|
||||
if (setup_emac_peripheral() != SUCCESS) {
|
||||
LOG_E("Failed to setup EMAC peripheral\r\n");
|
||||
return OBLFR_ERR_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
return OBLFR_OK;
|
||||
}
|
||||
|
||||
oblfr_err_t oblfr_mailbox_dump()
|
||||
{
|
||||
LOG_I("Mailbox IRQ Stats:\r\n");
|
||||
for (uint8_t i = 0; i < sizeof(ipc_irqs) / sizeof(ipc_irqs[0]); i++) {
|
||||
if (ipc_irqs[i].irq != 0) {
|
||||
LOG_I("Peripheral %s (%d): %d\r\n", ipc_irqs[i].name, ipc_irqs[i].irq, ipc_irqs[i].count);
|
||||
}
|
||||
}
|
||||
LOG_I("====================================\r\n");
|
||||
return OBLFR_OK;
|
||||
}
|
|
@ -5,6 +5,6 @@ config COMPONENT_TIMER
|
|||
help
|
||||
"Timer Component"
|
||||
menu "Timer Configuration"
|
||||
|
||||
visible if COMPONENT_TIMER
|
||||
|
||||
endmenu
|
||||
|
|
Loading…
Add table
Reference in a new issue