lock_lfvx/bk_idk/middleware/driver/mailbox/mailbox_driver_base.c
2025-10-10 16:07:00 +08:00

373 lines
10 KiB
C

// Copyright 2020-2021 Beken
//
// 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 <common/bk_include.h>
#include "mailbox_driver_base.h"
#include "mailbox_driver.h"
#include "icu_driver.h"
static const mailbox_config_t mailbox_cfg_map_table[] = MAILBAOX_CONFIG_INFO_TABLE;
static mailbox_info_t s_mailbox[ARRAY_SIZE(mailbox_cfg_map_table)] = {NULL};
static bool s_mailbox_is_init = false;
#define MAILBOX_RETURN_ON_NOT_INIT() do {\
if (!s_mailbox_is_init) {\
return BK_ERR_MAILBOX_NOT_INIT;\
}\
} while(0)
#define MAILBOX_RETURN_ON_REPEAT_INIT() do {\
if (s_mailbox_is_init) {\
return BK_ERR_MAILBOX_REPEAT_INIT;\
}\
} while(0)
static void mailbox_config(void);
static mailbox_id_t mailbox_check_src_dst(mailbox_endpoint_t src, mailbox_endpoint_t dst);
static void mailbox_write_data(mailbox_data_t *data, mailbox_id_t id, mailbox_box_num_t box);
static void mailbox_receive_data(mailbox_id_t id, mailbox_data_t *data, mailbox_box_num_t box);
static void mailbox_receive_isr(mailbox_id_t id);
static void mailbox_service0_isr(void);
static void mailbox_service1_isr(void);
static void mailbox_interrupt_service(mailbox_info_t *mailbox);
bk_err_t bk_mailbox_init(void)
{
MAILBOX_LOGD("Begin %s\n", __func__);
MAILBOX_RETURN_ON_REPEAT_INIT();
s_mailbox_is_init = true;
mailbox_config();
for(int index = 0; index < ARRAY_SIZE(mailbox_cfg_map_table); index++)
{
if (INT_SRC_NONE == s_mailbox[index].dir.icu_src)
continue;
bk_int_isr_register((s_mailbox[index].dir.icu_src),
(int_group_isr_t)(s_mailbox[index].imp.mailbox_isr), NULL);
mailbox_interrupt_enable(s_mailbox[index].dir.src);
}
MAILBOX_LOGD("End %s\n", __func__);
return BK_OK;
}
bk_err_t bk_mailbox_deinit(void)
{
MAILBOX_LOGD("Begin %s\n", __func__);
MAILBOX_RETURN_ON_NOT_INIT();
for(int index = 0; index < ARRAY_SIZE(mailbox_cfg_map_table); index++) {
mailbox_hal_box_init(&(s_mailbox[index].hal));
if (!(int_group_isr_t)(s_mailbox[index].imp.mailbox_isr))
continue;
bk_int_isr_unregister(s_mailbox[index].dir.icu_src);
mailbox_interrupt_disable(s_mailbox[index].dir.src);
}
s_mailbox_is_init = false;
MAILBOX_LOGD("End %s\n", __func__);
return BK_OK;
}
static void mailbox_config(void)
{
uint32_t index;
uint32_t m_id;
MAILBOX_LOGI("%s\n", __func__);
for (index = 0; index < ARRAY_SIZE(mailbox_cfg_map_table); index++) {
m_id = mailbox_cfg_map_table[index].id;
s_mailbox[m_id].hal.id = m_id;
s_mailbox[m_id].dir = mailbox_cfg_map_table[index];
mailbox_interrupt_service(&s_mailbox[m_id]);
if (mailbox_hal_addr_init(&(s_mailbox[m_id].hal)))
MAILBOX_LOGI("%s addr is error!\n", __func__);
MAILBOX_LOGD("%s addr is %x!\n", __func__, s_mailbox[m_id].hal);
mailbox_hal_set_identity(&(s_mailbox[m_id].hal));
mailbox_hal_box_init(&(s_mailbox[m_id].hal));
}
}
bk_err_t bk_mailbox_set_param(mailbox_data_t *data, uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3)
{
MAILBOX_RETURN_ON_NOT_INIT();
data->param0 = p0;
data->param1 = p1;
data->param2 = p2;
data->param3 = p3;
return BK_OK;
}
static mailbox_id_t mailbox_check_src_dst(mailbox_endpoint_t src, mailbox_endpoint_t dst)
{
for(int index = 0; index < ARRAY_SIZE(mailbox_cfg_map_table); index++)
{
if (s_mailbox[index].dir.src != src)
continue;
if (s_mailbox[index].dir.dst != dst)
continue;
return s_mailbox[index].hal.id;
}
MAILBOX_LOGD("%s is ERROR!\n", __func__);
return BK_ERR_MAILBOX_SRC_DST;
}
static void mailbox_write_data(mailbox_data_t *data, mailbox_id_t id, mailbox_box_num_t box)
{
mailbox_hal_write_param0(&(s_mailbox[id].hal), data->param0, box);
mailbox_hal_write_param1(&(s_mailbox[id].hal), data->param1, box);
mailbox_hal_write_param2(&(s_mailbox[id].hal), data->param2, box);
mailbox_hal_write_param3(&(s_mailbox[id].hal), data->param3, box);
MAILBOX_LOGD("[MAILBOX_SEND_PARAM]: (%08x, 0x%08x, %d, %d)\r\n", data->param0,
data->param1, data->param2, data->param3);
}
bk_err_t bk_mailbox_ready(mailbox_endpoint_t src, mailbox_endpoint_t dst, uint32_t box_id)
{
MAILBOX_RETURN_ON_NOT_INIT();
mailbox_id_t id;
mailbox_box_num_t box = (mailbox_box_num_t)box_id;
id = mailbox_check_src_dst(src, dst);
if (id >= ARRAY_SIZE(mailbox_cfg_map_table))
return BK_ERR_MAILBOX_SRC_DST;
if(mailbox_hal_read_box_ready(&(s_mailbox[id].hal), box) != 0)
{
return BK_ERR_MAILBOX_TIMEOUT; // mailbox busy
}
return BK_OK;
}
bk_err_t bk_mailbox_send(mailbox_data_t *data, mailbox_endpoint_t src, mailbox_endpoint_t dst, void *arg)
{
MAILBOX_RETURN_ON_NOT_INIT();
mailbox_id_t id;
mailbox_box_num_t box;
MAILBOX_LOGD("%s\n", __func__);
id = mailbox_check_src_dst(src, dst);
if (id >= ARRAY_SIZE(mailbox_cfg_map_table))
return BK_ERR_MAILBOX_SRC_DST;
MAILBOX_LOGD("mailbox send to %d\n", dst);
MAILBOX_LOGD("%s addr is %x! id: %d\n", __func__, (s_mailbox[id].hal), id);
if(arg == NULL)
{
int wait_count = 0;
while(wait_count < MAILBOX_SEND_WAIT_COUNT)
{
box = mailbox_hal_check_which_box_ready(&(s_mailbox[id].hal));
if (box != MAILBOX_NONE)
{
break;
}
wait_count++;
}
if (box == MAILBOX_NONE) // mailbox busy
return BK_ERR_MAILBOX_TIMEOUT;
}
else
{
box = (*(uint16_t *)arg) & 0xFF;
if ((box != MAILBOX_BOX0) && (box != MAILBOX_BOX1))
{
return BK_ERR_MAILBOX_ID;
}
if(mailbox_hal_read_box_ready(&(s_mailbox[id].hal), box) != 0)
{
return BK_ERR_MAILBOX_TIMEOUT; // mailbox busy
}
}
MAILBOX_LOGD("BOX: %x param0: %x, param1: %x, param2: %x, param3: %x\r\n",
box, data->param0, data->param1, data->param2, data->param3);
mailbox_hal_box_clear_ready(&(s_mailbox[id].hal), box);
mailbox_write_data(data, id, box);
mailbox_hal_box_trigger(&(s_mailbox[id].hal), box);
return BK_OK;
}
static void mailbox_receive_data(mailbox_id_t id, mailbox_data_t *data, mailbox_box_num_t box)
{
data->param0 = mailbox_hal_read_param0(&(s_mailbox[id].hal), box);
data->param1 = mailbox_hal_read_param1(&(s_mailbox[id].hal), box);
data->param2 = mailbox_hal_read_param2(&(s_mailbox[id].hal), box);
data->param3 = mailbox_hal_read_param3(&(s_mailbox[id].hal), box);
MAILBOX_LOGD("[MAILBOX_RECEIVE_PARAM]: (%08x, 0x%08x, %d, %d)\r\n", data->param0,
data->param1, data->param2, data->param3);
}
static void mailbox_receive_isr(mailbox_id_t id)
{
mailbox_data_t data;
mailbox_box_num_t box;
MAILBOX_LOGD("%s addr is %x! id: %d\n", __func__, (s_mailbox[id].hal), id);
box = mailbox_hal_check_which_box_trigger(&(s_mailbox[id].hal));
if (box == MAILBOX_NONE) {
MAILBOX_LOGD("%s BOX ERROR\n", __func__);
return;
}
mailbox_receive_data(id, &data, box);
mailbox_hal_box_clear(&(s_mailbox[id].hal), box);
for (int num = 0; num < MAILBOX_CALLBACK_NUMBER; num++)
{ if (s_mailbox[id].imp.rx[num] != NULL)
(s_mailbox[id].imp.rx[num])(&data);
}
MAILBOX_LOGD("[RECIVE_R]: (%08x, 0x%08x, %d, %d)\r\n", data.param0,
data.param1, data.param2, data.param3);
}
bk_err_t bk_mailbox_recv_callback_register(mailbox_endpoint_t src, mailbox_endpoint_t dst, mailbox_callback_t callback)
{
MAILBOX_RETURN_ON_NOT_INIT();
mailbox_id_t id;
MAILBOX_LOGI("%s\n", __func__);
id = mailbox_check_src_dst(src, dst);
if (id >= ARRAY_SIZE(mailbox_cfg_map_table))
return BK_ERR_MAILBOX_SRC_DST;
for (int num = 0; num < MAILBOX_CALLBACK_NUMBER; num++)
{
if ((NULL == s_mailbox[id].imp.rx[num]) || (callback == s_mailbox[id].imp.rx[num])) {
s_mailbox[id].imp.rx[num] = callback;
return BK_OK;
}
}
MAILBOX_LOGI("%s mailbox_cb is full\n", __func__);
return BK_ERR_MAILBOX_CALLBACK;
}
bk_err_t bk_mailbox_recv_callback_unregister(mailbox_endpoint_t src, mailbox_endpoint_t dst)
{
MAILBOX_RETURN_ON_NOT_INIT();
mailbox_id_t id;
MAILBOX_LOGI("%s\n", __func__);
id = mailbox_check_src_dst(src, dst);
if (id >= ARRAY_SIZE(mailbox_cfg_map_table))
return BK_ERR_MAILBOX_SRC_DST;
for (int num = 0; num < MAILBOX_CALLBACK_NUMBER; num++)
{ if (s_mailbox[id].imp.rx[num] != NULL) {
s_mailbox[id].imp.rx[num] = NULL;
return BK_OK;
}
}
MAILBOX_LOGI("%s 0x%x not found\n", __func__);
return BK_ERR_MAILBOX_CALLBACK;
}
static void mailbox_service0_isr(void)
{
MAILBOX_LOGD("%s INTO\n", __func__);
mailbox_id_t id = 0;
for(int index = 0; index < ARRAY_SIZE(mailbox_cfg_map_table); index++)
{
if (s_mailbox[index].dir.icu_src != INT_SRC_MAILBOX0)
continue;
id = s_mailbox[index].dir.id;
}
mailbox_receive_isr(id);
MAILBOX_LOGD("%s OUT\n", __func__);
}
static void mailbox_service1_isr(void)
{
MAILBOX_LOGD("%s INTO\n", __func__);
mailbox_id_t id = 0;
for(int index = 0; index < ARRAY_SIZE(mailbox_cfg_map_table); index++)
{
if (s_mailbox[index].dir.icu_src != INT_SRC_MAILBOX1)
continue;
id = s_mailbox[index].dir.id;
}
mailbox_receive_isr(id);
MAILBOX_LOGD("%s OUT\n", __func__);
}
static void mailbox_interrupt_service(mailbox_info_t *mailbox)
{
switch (mailbox->dir.icu_src){
case INT_SRC_MAILBOX0:
mailbox->imp.mailbox_isr = mailbox_service0_isr;
break;
case INT_SRC_MAILBOX1:
mailbox->imp.mailbox_isr = mailbox_service1_isr;
break;
default:
break;
}
}
//TWO function for other projects
void mailbox_driver_init(void)
{
MAILBOX_LOGD("%s mailbox driver INIT!!!\n", __func__);
bk_mailbox_init();
}
void mailbox_driver_deinit(void)
{
bk_mailbox_deinit();
}