437 lines
10 KiB
C
437 lines
10 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (C) 2021 MediaTek Inc.
|
|
*/
|
|
|
|
#include "ccci_util_lib_main.h"
|
|
|
|
/*------------------------------------------*/
|
|
#define MD_CAP_BIT_NUM (7)
|
|
|
|
/*------------------------------------------*/
|
|
/* Bit map defination at MD side diff to AP */
|
|
/* 0 | 0 | Lf | Lt | W | C | T | G */
|
|
#define MD_CAP_GSM (1<<0)
|
|
#define MD_CAP_TDS_CDMA (1<<1)
|
|
#define MD_CAP_WCDMA (1<<3)
|
|
#define MD_CAP_TDD_LTE (1<<4)
|
|
#define MD_CAP_FDD_LTE (1<<5)
|
|
#define MD_CAP_CDMA2000 (1<<2)
|
|
#define MD_CAP_NR (1<<6)
|
|
|
|
#define MD_CAP_FULL_SET (MD_CAP_GSM|MD_CAP_TDS_CDMA| \
|
|
MD_CAP_WCDMA|MD_CAP_TDD_LTE| \
|
|
MD_CAP_FDD_LTE|MD_CAP_CDMA2000|MD_CAP_NR)
|
|
|
|
/* Note: this must keep sync with md_rat_map table.
|
|
* If MD_CAP_FULL_SET change or md_rat_map table change, this macro should change too.
|
|
*/
|
|
#define MD_CAP_FULL_SET_IDX (24)
|
|
|
|
static const unsigned int md_img_capability_map[] = { /* At check header */
|
|
|
|
/* 0 - None */
|
|
0,
|
|
|
|
/* 1 - G */
|
|
MD_CAP_GSM,
|
|
|
|
/* 2 - W */
|
|
MD_CAP_WCDMA,
|
|
|
|
/* 3 - WG = W + G */
|
|
(MD_CAP_WCDMA|MD_CAP_GSM),
|
|
|
|
/* 4 - TG = T + G */
|
|
(MD_CAP_TDS_CDMA|MD_CAP_GSM),
|
|
|
|
/* 5 - LWG = Lf + Lt + T + G */
|
|
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_GSM),
|
|
|
|
/* 6 - LTG = Lf + Lt + T + G */
|
|
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_TDS_CDMA|MD_CAP_GSM),
|
|
|
|
/* 7 - SGLTE = Lf + Lt + T + G (Phase out)*/
|
|
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_TDS_CDMA|MD_CAP_GSM),
|
|
|
|
/* 8 - LTG = Lf + Lt + T + G */
|
|
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_TDS_CDMA|MD_CAP_GSM),
|
|
|
|
/* 9 - LWG = Lf + Lt + W + G */
|
|
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_GSM),
|
|
|
|
/* 10 - LWTG = Lf + Lt + W + T + G */
|
|
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_TDS_CDMA|MD_CAP_GSM),
|
|
|
|
/* 11 - LWCG = Lf + Lt + W + C + G */
|
|
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_CDMA2000|MD_CAP_GSM),
|
|
|
|
/* 12 - LWCTG = N + Lf + Lt + W + C + T + G */
|
|
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_CDMA2000
|
|
|MD_CAP_TDS_CDMA|MD_CAP_GSM),
|
|
|
|
/* 13 - NLWTG = N + Lf + Lt + W + T + G */
|
|
(MD_CAP_NR|MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA
|
|
|MD_CAP_TDS_CDMA|MD_CAP_GSM),
|
|
|
|
/* 14 - NLWCG = N + Lf + Lt + W + C + G */
|
|
(MD_CAP_NR|MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA
|
|
|MD_CAP_CDMA2000|MD_CAP_GSM),
|
|
|
|
/* 15 - NL = N + Lf + Lt */
|
|
(MD_CAP_NR|MD_CAP_FDD_LTE|MD_CAP_TDD_LTE),
|
|
};
|
|
|
|
static const unsigned int md_rat_map[] = { /* Options supplied by MD */
|
|
/* 0 ~ 7 not userd */
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
/* ultg - 8 */
|
|
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_TDS_CDMA|MD_CAP_GSM),
|
|
|
|
/* ulwg - 9 */
|
|
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_GSM),
|
|
|
|
/* ulwtg - 10 */
|
|
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_TDS_CDMA|MD_CAP_GSM),
|
|
|
|
/* ulwcg - 11 */
|
|
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_CDMA2000|MD_CAP_GSM),
|
|
|
|
/* ulwctg -12 */
|
|
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_CDMA2000
|
|
|MD_CAP_TDS_CDMA|MD_CAP_GSM),
|
|
|
|
/* ulttg - 13 */
|
|
(MD_CAP_TDD_LTE|MD_CAP_TDS_CDMA|MD_CAP_GSM),
|
|
|
|
/* ulfwg - 14 */
|
|
(MD_CAP_FDD_LTE|MD_CAP_WCDMA|MD_CAP_GSM),
|
|
|
|
/* ulfwcg - 15 */
|
|
(MD_CAP_FDD_LTE|MD_CAP_WCDMA|MD_CAP_CDMA2000|MD_CAP_GSM),
|
|
|
|
/* ulctg - 16 */
|
|
(MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_CDMA2000|MD_CAP_TDS_CDMA
|
|
|MD_CAP_GSM),
|
|
|
|
/* ultctg - 17 */
|
|
(MD_CAP_TDD_LTE|MD_CAP_CDMA2000|MD_CAP_TDS_CDMA|MD_CAP_GSM),
|
|
|
|
/*ultwg - 18 */
|
|
(MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_GSM),
|
|
|
|
/* ultwcg -19 */
|
|
(MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_CDMA2000|MD_CAP_GSM),
|
|
|
|
/* ulftg - 20 */
|
|
(MD_CAP_FDD_LTE|MD_CAP_TDS_CDMA|MD_CAP_GSM),
|
|
|
|
/* ulfctg - 21 */
|
|
(MD_CAP_FDD_LTE|MD_CAP_CDMA2000|MD_CAP_TDS_CDMA|MD_CAP_GSM),
|
|
|
|
/* unlwg - 22 */
|
|
(MD_CAP_NR|MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA
|
|
|MD_CAP_GSM),
|
|
|
|
/* unlwtg - 23 */
|
|
(MD_CAP_NR|MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA
|
|
|MD_CAP_TDS_CDMA|MD_CAP_GSM),
|
|
|
|
/* unlwctg - 24 */
|
|
(MD_CAP_NR|MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA|MD_CAP_CDMA2000
|
|
|MD_CAP_TDS_CDMA|MD_CAP_GSM),
|
|
|
|
/* unlwcg - 25 */
|
|
(MD_CAP_NR|MD_CAP_FDD_LTE|MD_CAP_TDD_LTE|MD_CAP_WCDMA
|
|
|MD_CAP_CDMA2000|MD_CAP_GSM),
|
|
|
|
/* unltctg - 26 */
|
|
(MD_CAP_NR|MD_CAP_TDD_LTE|MD_CAP_CDMA2000
|
|
|MD_CAP_TDS_CDMA|MD_CAP_GSM),
|
|
|
|
/* unl - 27 */
|
|
(MD_CAP_NR|MD_CAP_FDD_LTE|MD_CAP_TDD_LTE),
|
|
};
|
|
|
|
static unsigned int get_bit_set_num(unsigned int bitmap)
|
|
{
|
|
unsigned int i;
|
|
unsigned int num = 0;
|
|
unsigned int curr_bit = 1;
|
|
|
|
for (i = 0; i < MD_CAP_BIT_NUM; i++) {
|
|
if (bitmap & curr_bit)
|
|
num++;
|
|
curr_bit = curr_bit << 1;
|
|
}
|
|
return num;
|
|
}
|
|
|
|
static unsigned int get_rat_id_by_bitmap(unsigned int rat_bit_map)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(md_rat_map); i++) {
|
|
if (rat_bit_map == md_rat_map[i])
|
|
return i;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static unsigned int find_prefer_val(unsigned int ref_rat, unsigned int *idx)
|
|
{
|
|
unsigned int i;
|
|
unsigned int min_bitmap, min_bitmap_num, num;
|
|
unsigned int idx_at_support_list = MD_CAP_FULL_SET_IDX;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(md_rat_map); i++) {
|
|
if (ref_rat == md_rat_map[i]) {
|
|
if (idx)
|
|
*idx = i;
|
|
return ref_rat;
|
|
}
|
|
}
|
|
|
|
/* Use the most similar settings */
|
|
min_bitmap = MD_CAP_FULL_SET;
|
|
min_bitmap_num = get_bit_set_num(min_bitmap);
|
|
|
|
for (i = 0; i < ARRAY_SIZE(md_rat_map); i++) {
|
|
if ((ref_rat & md_rat_map[i]) != ref_rat)
|
|
continue;
|
|
num = get_bit_set_num(md_rat_map[i]);
|
|
if (min_bitmap_num > num) {
|
|
min_bitmap = md_rat_map[i];
|
|
min_bitmap_num = num;
|
|
idx_at_support_list = i;
|
|
}
|
|
}
|
|
|
|
if (idx)
|
|
*idx = idx_at_support_list;
|
|
return min_bitmap;
|
|
}
|
|
|
|
static unsigned int get_capability_bit(char cap_str[])
|
|
{
|
|
if (cap_str == NULL)
|
|
return 0;
|
|
|
|
if ((strcmp(cap_str, "N") == 0) || (strcmp(cap_str, "n") == 0))
|
|
return MD_CAP_NR;
|
|
|
|
if ((strcmp(cap_str, "LF") == 0) || (strcmp(cap_str, "Lf") == 0)
|
|
|| (strcmp(cap_str, "lf") == 0))
|
|
return MD_CAP_FDD_LTE;
|
|
|
|
if ((strcmp(cap_str, "LT") == 0) || (strcmp(cap_str, "Lt") == 0)
|
|
|| (strcmp(cap_str, "lt") == 0))
|
|
return MD_CAP_TDD_LTE;
|
|
|
|
if ((strcmp(cap_str, "W") == 0) || (strcmp(cap_str, "w") == 0))
|
|
return MD_CAP_WCDMA;
|
|
|
|
if ((strcmp(cap_str, "C") == 0) || (strcmp(cap_str, "c") == 0))
|
|
return MD_CAP_CDMA2000;
|
|
|
|
if ((strcmp(cap_str, "T") == 0) || (strcmp(cap_str, "t") == 0))
|
|
return MD_CAP_TDS_CDMA;
|
|
|
|
if ((strcmp(cap_str, "G") == 0) || (strcmp(cap_str, "g") == 0))
|
|
return MD_CAP_GSM;
|
|
|
|
return 0;
|
|
}
|
|
|
|
#define MAX_CAP_STR_LENGTH 64
|
|
static unsigned int ccci_rat_str_to_bitmap(char str[])
|
|
{
|
|
char tmp_str[MAX_CAP_STR_LENGTH];
|
|
unsigned int tmp_str_curr_pos = 0;
|
|
unsigned int bitmap = 0;
|
|
int str_len;
|
|
int i;
|
|
|
|
if (str == NULL)
|
|
return 0;
|
|
|
|
str_len = strlen(str);
|
|
for (i = 0; i < str_len; i++) {
|
|
if (str[i] == ' ')
|
|
continue;
|
|
if (str[i] == '\t')
|
|
continue;
|
|
if ((str[i] == '/') || (str[i] == '\\') || (str[i] == '_')) {
|
|
if (tmp_str_curr_pos) {
|
|
tmp_str[tmp_str_curr_pos] = 0;
|
|
bitmap |= get_capability_bit(tmp_str);
|
|
}
|
|
tmp_str_curr_pos = 0;
|
|
continue;
|
|
}
|
|
if (tmp_str_curr_pos < (MAX_CAP_STR_LENGTH-1)) {
|
|
tmp_str[tmp_str_curr_pos] = str[i];
|
|
tmp_str_curr_pos++;
|
|
} else
|
|
break;
|
|
}
|
|
|
|
if (tmp_str_curr_pos) {
|
|
tmp_str[tmp_str_curr_pos] = 0;
|
|
bitmap |= get_capability_bit(tmp_str);
|
|
}
|
|
|
|
return bitmap;
|
|
}
|
|
|
|
unsigned int mtk_ccci_get_md_img_cap(void)
|
|
{
|
|
unsigned int value = 0;
|
|
|
|
if (mtk_ccci_find_args_val("md_capability", (unsigned char *)&value, sizeof(unsigned int))
|
|
!= sizeof(unsigned int))
|
|
pr_info("ccci: %s: get MD CAP fail\n", __func__);
|
|
|
|
return value;
|
|
}
|
|
EXPORT_SYMBOL(mtk_ccci_get_md_img_cap);
|
|
|
|
|
|
unsigned int get_md_bin_capability(void)
|
|
{
|
|
int img_type;
|
|
|
|
img_type = get_md_img_type();
|
|
if (img_type < 0)
|
|
return 0;
|
|
|
|
if (img_type < ARRAY_SIZE(md_img_capability_map))
|
|
return md_img_capability_map[img_type];
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(get_md_bin_capability);
|
|
|
|
int check_rat_at_md_img(char str[])
|
|
{
|
|
unsigned int rat, cap;
|
|
|
|
rat = get_capability_bit(str);
|
|
cap = get_md_bin_capability();
|
|
|
|
if (rat & cap)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(check_rat_at_md_img);
|
|
|
|
|
|
static unsigned int s_md_rt_wm_id_bitmap;
|
|
static unsigned int s_md_rt_wm_id;
|
|
|
|
void set_soc_md_rt_rat(unsigned int bitmap, unsigned int id)
|
|
{
|
|
s_md_rt_wm_id_bitmap = bitmap;
|
|
s_md_rt_wm_id = id;
|
|
}
|
|
EXPORT_SYMBOL(set_soc_md_rt_rat);
|
|
|
|
unsigned int get_soc_md_rt_rat(void)
|
|
{
|
|
return s_md_rt_wm_id_bitmap;
|
|
}
|
|
EXPORT_SYMBOL(get_soc_md_rt_rat);
|
|
|
|
unsigned int get_soc_md_rt_rat_idx(void)
|
|
{
|
|
return s_md_rt_wm_id;
|
|
}
|
|
EXPORT_SYMBOL(get_soc_md_rt_rat_idx);
|
|
|
|
int check_rat_at_rt_setting(char str[])
|
|
{
|
|
unsigned int rat, cap;
|
|
|
|
rat = get_capability_bit(str);
|
|
cap = get_soc_md_rt_rat();
|
|
|
|
if (rat & cap)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(check_rat_at_rt_setting);
|
|
|
|
|
|
int set_soc_md_rt_rat_by_idx(unsigned int wm_idx)
|
|
{
|
|
unsigned int rat_bitmap, cap;
|
|
|
|
cap = get_md_bin_capability();
|
|
if (!wm_idx)
|
|
return -1;
|
|
|
|
if (wm_idx >= ARRAY_SIZE(md_rat_map)) {
|
|
pr_info("CCCI: %s get not support wm_idx:%u\n", __func__, wm_idx);
|
|
return -1;
|
|
}
|
|
rat_bitmap = md_rat_map[wm_idx];
|
|
if (!rat_bitmap) {
|
|
pr_info("CCCI: %s get invalid wm_idx:%u\n", __func__, wm_idx);
|
|
return -1;
|
|
}
|
|
|
|
if ((rat_bitmap & cap) != rat_bitmap) {
|
|
pr_info("CCCI:%s: md img cap not support wm_idx: %u [c:0x%x|s:0x%x]\n",
|
|
__func__, wm_idx, cap, rat_bitmap);
|
|
return -1;
|
|
}
|
|
|
|
set_soc_md_rt_rat(rat_bitmap, wm_idx);
|
|
pr_info("CCCI:%s:wm_idx[%u][c:0x%x|s:0x%x]\n", __func__, wm_idx, cap, rat_bitmap);
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(set_soc_md_rt_rat_by_idx);
|
|
|
|
int set_soc_md_rt_rat_str(char str[])
|
|
{
|
|
unsigned int rat_bitmap, prefer, cap, id;
|
|
|
|
cap = get_md_bin_capability();
|
|
id = get_rat_id_by_bitmap(cap);
|
|
|
|
if (id == 0) {
|
|
pr_info("CCCI: %s: should not run to here. MD cap not in support list!\n",
|
|
__func__);
|
|
return -1;
|
|
}
|
|
|
|
if (!str) {
|
|
pr_info("CCCI: %s get NULL ptr!\n", __func__);
|
|
set_soc_md_rt_rat(cap, id);
|
|
return 1;
|
|
}
|
|
|
|
if (strlen(str) == 0) {
|
|
pr_info("CCCI: %s str empty, set default value!\n", __func__);
|
|
set_soc_md_rt_rat(cap, id);
|
|
return 1;
|
|
}
|
|
|
|
rat_bitmap = ccci_rat_str_to_bitmap(str);
|
|
prefer = find_prefer_val(rat_bitmap, &id);
|
|
|
|
if ((prefer == 0) || ((prefer & cap) != prefer)) {
|
|
pr_info("CCCI:%s:rat[%s](r:0x%x|p:0x%x|c:0x%x) not support!\n",
|
|
__func__, str, rat_bitmap, prefer, cap);
|
|
set_soc_md_rt_rat(cap, id);
|
|
return 1;
|
|
}
|
|
set_soc_md_rt_rat(prefer, id);
|
|
pr_info("CCCI:%s:rat[%s](r:0x%x|p:0x%x|c:0x%x)[%u]\n",
|
|
__func__, str, rat_bitmap, prefer, cap, id);
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(set_soc_md_rt_rat_str);
|