// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2016 MediaTek Inc. */ #include #include #include #include /* local_clock() */ #include #include //#include 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; 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, };