unplugged-kernel/drivers/misc/mediatek/eccci/port/port_sysmsg.c

278 lines
6.8 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2016 MediaTek Inc.
*/
#include <linux/device.h>
#include <linux/wait.h>
#include <linux/module.h>
#include <linux/sched/clock.h> /* local_clock() */
#include <linux/kthread.h>
#include <linux/kernel.h>
//#include <mt-plat/mtk_battery.h> fixme
#include "ccci_auxadc.h"
#include "ccci_config.h"
#include "ccci_common_config.h"
#include "ccci_core.h"
#include "ccci_bm.h"
#include "port_sysmsg.h"
#include "ccci_swtp.h"
#define MAX_QUEUE_LENGTH 16
struct md_rf_notify_struct {
unsigned int bit;
void (*notify_func)(unsigned int para0, unsigned int para1);
const char *module_name;
};
#define MD_RF_NOTIFY(bit, func, name) \
__weak void func(unsigned int para0, unsigned int para1) \
{ \
pr_debug("[ccci1/SYS]weak %s", __func__); \
}
#include "mdrf_notify_list.h"
#undef MD_RF_NOTIFY
#define MD_RF_NOTIFY(bit, func, name) \
{bit, func, name},
static struct md_rf_notify_struct notify_members[] = {
#include "mdrf_notify_list.h"
};
#define NOTIFY_LIST_ITM_NUM ARRAY_SIZE(notify_members)
static void sys_msg_MD_RF_Notify(int md_id, unsigned int bit_value,
unsigned int data_1)
{
int i;
unsigned int data_send;
for (i = 0; i < NOTIFY_LIST_ITM_NUM; i++) {
data_send = (bit_value&(1<<notify_members[i].bit))
>> notify_members[i].bit;
CCCI_NORMAL_LOG(md_id, SYS, "0x121: notify to (%s)\n",
notify_members[i].module_name);
notify_members[i].notify_func(data_send, data_1);
}
}
#ifndef TEST_MESSAGE_FOR_BRINGUP
#define TEST_MESSAGE_FOR_BRINGUP
#endif
#ifdef TEST_MESSAGE_FOR_BRINGUP
static inline int port_sys_notify_md(struct port_t *port, unsigned int msg,
unsigned int data)
{
return port_send_msg_to_md(port, msg, data, 1);
}
static inline int port_sys_echo_test(struct port_t *port, int data)
{
CCCI_DEBUG_LOG(port->md_id, SYS,
"system message: Enter ccci_sysmsg_echo_test data= %08x",
data);
port_sys_notify_md(port, TEST_MSG_ID_AP2MD, data);
return 0;
}
static inline int port_sys_echo_test_l1core(struct port_t *port, int data)
{
CCCI_DEBUG_LOG(port->md_id, SYS,
"system message: Enter ccci_sysmsg_echo_test_l1core data= %08x",
data);
port_sys_notify_md(port, TEST_MSG_ID_L1CORE_AP2MD, data);
return 0;
}
#endif
/* for backward compatibility */
struct ccci_sys_cb_func_info ccci_sys_cb_table_100[MAX_MD_NUM][MAX_KERN_API];
struct ccci_sys_cb_func_info ccci_sys_cb_table_1000[MAX_MD_NUM][MAX_KERN_API];
int register_ccci_sys_call_back(int md_id, unsigned int id,
ccci_sys_cb_func_t func)
{
int ret = 0;
struct ccci_sys_cb_func_info *info_ptr = NULL;
if (md_id >= MAX_MD_NUM) {
CCCI_ERROR_LOG(md_id, SYS,
"register_sys_call_back fail: invalid md id\n");
return -EINVAL;
}
if ((id >= 0x100) && ((id - 0x100) < MAX_KERN_API)) {
info_ptr = &(ccci_sys_cb_table_100[md_id][id - 0x100]);
} else if ((id >= 0x1000) && ((id - 0x1000) < MAX_KERN_API)) {
info_ptr = &(ccci_sys_cb_table_1000[md_id][id - 0x1000]);
} else {
CCCI_ERROR_LOG(md_id, SYS,
"register_sys_call_back fail: invalid func id(0x%x)\n",
id);
return -EINVAL;
}
if (info_ptr->func == NULL) {
info_ptr->id = id;
info_ptr->func = func;
} else {
CCCI_ERROR_LOG(md_id, SYS,
"register_sys_call_back fail: func(0x%x) registered! %ps\n",
id, info_ptr->func);
}
return ret;
}
void exec_ccci_sys_call_back(int md_id, int cb_id, int data)
{
ccci_sys_cb_func_t func;
int id;
struct ccci_sys_cb_func_info *curr_table = NULL;
if (md_id >= MAX_MD_NUM) {
CCCI_ERROR_LOG(md_id, SYS,
"exec_sys_cb fail: invalid md id\n");
return;
}
id = cb_id & 0xFF;
if (id >= MAX_KERN_API) {
CCCI_ERROR_LOG(md_id, SYS,
"exec_sys_cb fail: invalid func id(0x%x)\n", cb_id);
return;
}
if ((cb_id & (0x1000 | 0x100)) == 0x1000) {
curr_table = ccci_sys_cb_table_1000[md_id];
} else if ((cb_id & (0x1000 | 0x100)) == 0x100) {
curr_table = ccci_sys_cb_table_100[md_id];
} else {
CCCI_ERROR_LOG(md_id, SYS,
"exec_sys_cb fail: invalid func id(0x%x)\n", cb_id);
return;
}
func = curr_table[id].func;
if (func != NULL)
func(md_id, data);
else
CCCI_ERROR_LOG(md_id, SYS,
"exec_sys_cb fail: func id(0x%x) not register!\n",
cb_id);
}
signed int __weak battery_get_bat_voltage(void)
{
pr_debug("[ccci/dummy] %s is not supported!\n", __func__);
return 0;
}
static int sys_msg_send_battery(struct port_t *port)
{
int data;
data = (int)battery_get_bat_voltage();
CCCI_REPEAT_LOG(port->md_id, SYS, "get bat voltage %d\n", data);
port_send_msg_to_md(port, MD_GET_BATTERY_INFO, data, 1);
return 0;
}
static void sys_msg_handler(struct port_t *port, struct sk_buff *skb)
{
struct ccci_header *ccci_h = (struct ccci_header *)skb->data;
int md_id = port->md_id;
unsigned long rem_nsec;
u64 ts_nsec, ref;
CCCI_NORMAL_LOG(md_id, SYS, "system message (%x %x %x %x)\n",
ccci_h->data[0], ccci_h->data[1],
ccci_h->channel, ccci_h->reserved);
ts_nsec = sched_clock();
ref = ts_nsec;
rem_nsec = do_div(ts_nsec, 1000000000);
CCCI_HISTORY_LOG(md_id, SYS, "[%5lu.%06lu]sysmsg-%08x %08x %04x\n",
(unsigned long)ts_nsec, rem_nsec / 1000,
ccci_h->data[1], ccci_h->reserved, ccci_h->seq_num);
switch (ccci_h->data[1]) {
case MD_WDT_MONITOR:
/* abandoned */
break;
#ifdef TEST_MESSAGE_FOR_BRINGUP
case TEST_MSG_ID_MD2AP:
port_sys_echo_test(port, ccci_h->reserved);
break;
case TEST_MSG_ID_L1CORE_MD2AP:
port_sys_echo_test_l1core(port, ccci_h->reserved);
break;
#endif
#ifdef CONFIG_MTK_SIM_LOCK_POWER_ON_WRITE_PROTECT
case SIM_LOCK_RANDOM_PATTERN:
fsm_monitor_send_message(md_id, CCCI_MD_MSG_RANDOM_PATTERN, 0);
break;
#endif
#ifdef FEATURE_SCP_CCCI_SUPPORT
case CCISM_SHM_INIT_ACK:
/* Fall through */
#endif
case MD_SIM_TYPE:
/* Fall through */
case MD_TX_POWER:
/* Fall through */
case MD_RF_TEMPERATURE:
/* Fall through */
case MD_RF_TEMPERATURE_3G:
/* Fall through */
case MD_SW_MD1_TX_POWER_REQ:
/* Fall through */
case MD_DISPLAY_DYNAMIC_MIPI:
/* Fall through */
case LWA_CONTROL_MSG:
exec_ccci_sys_call_back(md_id, ccci_h->data[1],
ccci_h->reserved);
break;
case MD_GET_BATTERY_INFO:
sys_msg_send_battery(port);
break;
case MD_RF_HOPPING_NOTIFY:
sys_msg_MD_RF_Notify(md_id, ccci_h->reserved, ccci_h->data[0]);
break;
};
ccci_free_skb(skb);
ts_nsec = sched_clock();
#ifdef __LP64__
rem_nsec = (unsigned long)((ts_nsec - ref) / 1000);
#else
ts_nsec = ts_nsec - ref;
rem_nsec = do_div(ts_nsec, 1000LL);
#endif
CCCI_HISTORY_LOG(md_id, SYS, "cost: %lu us\n", rem_nsec);
}
static int port_sys_init(struct port_t *port)
{
CCCI_DEBUG_LOG(port->md_id, SYS,
"kernel port %s is initializing\n", port->name);
if (port->md_id == MD_SYS1)
swtp_init(port->md_id);
port->skb_handler = &sys_msg_handler;
port->private_data = kthread_run(port_kthread_handler, port, "%s",
port->name);
port->rx_length_th = MAX_QUEUE_LENGTH;
port->skb_from_pool = 1;
return 0;
}
struct port_ops sys_port_ops = {
.init = &port_sys_init,
.recv_skb = &port_recv_skb,
};