• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  *
15  * Description: Provides tcxo trim port \n
16  *
17  * History: \n
18  * 2024-01-31, Create file. \n
19  */
20 #include "xo_trim_porting.h"
21 #include "efuse.h"
22 #include "efuse_porting.h"
23 #include "clock_init.h"
24 #include "chip_io.h"
25 #include "soc_osal.h"
26 #ifdef CONFIG_MIDDLEWARE_SUPPORT_NV
27 #include "nv.h"
28 #include "tsensor.h"
29 #endif
30 
cmu_xo_trim_reg_set(uint32_t fine,uint32_t coarse)31 static void cmu_xo_trim_reg_set(uint32_t fine, uint32_t coarse)
32 {
33     u_cmu_xo_sig val;
34 
35     val.u32 = readl(CMU_XO_SIG);
36     val.bits.rg_cmu_xo_trim_coarse = coarse;
37     val.bits.rg_cmu_xo_trim_fine = fine;
38     val.bits.rg_cmu_xo_trim_coarse_sel = XO_TRIM_ENABLE;
39     val.bits.rg_cmu_xo_trim_fine_sel = XO_TRIM_ENABLE;
40     writel(CMU_XO_SIG, val.u32);
41 }
42 
cmu_xo_trim_init(void)43 void cmu_xo_trim_init(void)
44 {
45     uint8_t lock = 0;
46     uint16_t value = 0;
47     int index;
48     uint8_t writable = false;
49     uint32_t fine = 0;
50     uint32_t coarse = 0;
51     uint32_t id[EFUSE_GROUP_MAX] = {EXT_EFUSE_XO_TRIM_1_ID, EXT_EFUSE_XO_TRIM_2_ID, EXT_EFUSE_XO_TRIM_3_ID};
52     uint32_t lock_id[EFUSE_GROUP_MAX] = {
53         EXT_EFUSE_RSSI_BAND3_1_ID, EXT_EFUSE_RSSI_BAND3_2_ID, EXT_EFUSE_RSSI_BAND3_3_ID
54     };
55 
56     for (index = (EFUSE_GROUP_MAX - 1); index >= 0; --index) {
57         if (uapi_efuse_read_bit(&lock, lock_id[index], EXT_EFUSE_LOCK_XO_TRIM_BIT_POS) != SUCC) {
58             return;
59         }
60         writable = (lock == 0) ? false : true;
61         if (writable == false) {
62             continue;
63         }
64         if (uapi_efuse_read_buffer((uint8_t *)&value, id[index], sizeof(value)) != SUCC) {
65             return;
66         }
67         break;
68     }
69     if (writable == false) {
70         return;
71     }
72     value = (value & 0xFFF);
73     fine = (value & 0xFF);
74     coarse = ((value >> SIZE_8_BITS) & 0xF);
75     cmu_xo_trim_reg_set(fine, coarse);
76     return;
77 }
78 #if defined(CONFIG_MIDDLEWARE_SUPPORT_NV)
79 #define CMU_XO_TRIM_TEMP_PARAM_NUM 8    // 8个温度档位值(fine值)(~-20,0,20,40,60,80,100,100~)
80 #define CMU_XO_TRIM_TEMP_TIMER_LEN 2000 // 2000ms
81 #define CMU_XO_TRIM_TEMP_LOW (-40)      // 频偏粗调温补使用温度范围的最低温 用于档位计算
82 #define CMU_XO_TRIM_TEMP_GAP (20)       // 温度档位的间隔20度
83 #define CMU_XO_TRIM_TEMP_CODE (3)       // 温度档位默认值 对应20~40度
84 #define CMU_XO_TRIM_FINE_CODE_MAX (127) // 最大可调的fine code值
85 osal_timer g_xo_trim_temp_timer;
86 int8_t g_nv_xo_trim_temp_fine_code[CMU_XO_TRIM_TEMP_PARAM_NUM] = {0};
cmu_xo_trim_temp_comp_timer_proc(uint32_t para)87 static void cmu_xo_trim_temp_comp_timer_proc(uint32_t para)
88 {
89     int32_t ret = SUCC;
90     static uint8_t last_temp_code = 255;
91     int8_t cur_temp = 25; // 常温
92     uint8_t temp_code = CMU_XO_TRIM_TEMP_CODE;
93     if (uapi_tsensor_get_current_temp(&cur_temp) == SUCC) {
94         if (cur_temp < CMU_XO_TRIM_TEMP_LOW) {
95             cur_temp = CMU_XO_TRIM_TEMP_LOW;
96         }
97         temp_code = (uint8_t)((cur_temp - CMU_XO_TRIM_TEMP_LOW) / CMU_XO_TRIM_TEMP_GAP);
98         if (temp_code >= CMU_XO_TRIM_TEMP_PARAM_NUM) {
99             temp_code = CMU_XO_TRIM_TEMP_PARAM_NUM - 1;
100         }
101         // 确保上一次的温度码有效 并且当前温度码与上一次不同 执行fine code的刷新
102         if (last_temp_code != temp_code) {
103             u_cmu_xo_sig val;
104             val.u32 = para;
105             int32_t new_fine = (int32_t)val.bits.rg_cmu_xo_trim_fine + g_nv_xo_trim_temp_fine_code[temp_code];
106             new_fine = (new_fine < 0) ? 0 : (new_fine > CMU_XO_TRIM_FINE_CODE_MAX) ?
107                 CMU_XO_TRIM_FINE_CODE_MAX : new_fine;
108             val.bits.rg_cmu_xo_trim_fine = (uint32_t)new_fine; // 取值范围0-127
109             writel(CMU_XO_SIG, val.u32);
110             last_temp_code = temp_code;
111 #ifdef SW_UART_DEBUG
112             osal_printk("xo update temp:%u,diff:%d,xo:0x%x\r\n",
113                 temp_code, g_nv_xo_trim_temp_fine_code[temp_code], val.u32);
114 #endif
115         }
116     }
117     ret = osal_timer_mod(&g_xo_trim_temp_timer, CMU_XO_TRIM_TEMP_TIMER_LEN);
118     if (ret != SUCC) {
119         osal_printk("xo_trim_temp_comp timer mod err ret:%u!\r\n", ret);
120     }
121 }
cmu_xo_trim_temp_comp_init(void)122 void cmu_xo_trim_temp_comp_init(void)
123 {
124     uint32_t ret;
125     uint8_t sw = 0;
126     uint16_t nv_param_len = 0;
127     if (uapi_nv_read(NV_ID_SYSTEM_XO_TRIM_TEMP_SW, 1, &nv_param_len, &sw) != SUCC) {
128         osal_printk("xo_trim_temp_comp::nv read sw fail!\r\n");
129         return;
130     }
131     // 开关开启的情况下 启动定时器 查询温度 执行温补
132     if (sw == 0) {
133         return;
134     }
135     if (uapi_nv_read(NV_ID_SYSTEM_XO_TRIM_TEMP_PARAM, CMU_XO_TRIM_TEMP_PARAM_NUM, &nv_param_len,
136         (uint8_t *)g_nv_xo_trim_temp_fine_code) != SUCC) {
137         osal_printk("xo_trim_temp_comp::nv read param fail!\r\n");
138         return;
139     }
140 #ifdef SW_UART_DEBUG
141     osal_printk("xo_trim_temp_comp val:%d %d\r\n", g_nv_xo_trim_temp_fine_code[0],
142         g_nv_xo_trim_temp_fine_code[CMU_XO_TRIM_TEMP_PARAM_NUM - 1]);
143 #endif
144     g_xo_trim_temp_timer.timer = NULL; /* 初始化需要置空 */
145     g_xo_trim_temp_timer.handler = (void *)cmu_xo_trim_temp_comp_timer_proc;
146     g_xo_trim_temp_timer.data = readl(CMU_XO_SIG);                     // 默认的频偏值
147     g_xo_trim_temp_timer.interval = (CMU_XO_TRIM_TEMP_TIMER_LEN << 1); // 首次触发4s 后续2s间隔查询
148     ret = (uint32_t)osal_timer_init(&g_xo_trim_temp_timer);
149     ret |= (uint32_t)osal_timer_start(&g_xo_trim_temp_timer);
150     if (ret != SUCC) {
151         osal_printk("xo_trim_temp_comp timer err ret:%u!\r\n", ret);
152     }
153 }
cmu_xo_trim_temp_comp_print(void)154 void cmu_xo_trim_temp_comp_print(void)
155 {
156     uint32_t i;
157     uint8_t sw = 0;
158     uint16_t nv_param_len = 0;
159     if (uapi_nv_read(NV_ID_SYSTEM_XO_TRIM_TEMP_SW, 1, &nv_param_len, &sw) != SUCC) {
160         osal_printk("xo_trim_temp_comp::nv read sw fail!\r\n");
161         return;
162     }
163     // 开关开启的情况下 启动定时器 查询温度 执行温补
164     if (sw == 0) {
165         osal_printk("xo_trim_temp_comp::switch off!\r\n");
166         return;
167     }
168     for (i = 0; i < CMU_XO_TRIM_TEMP_PARAM_NUM - 1; i++) {
169         osal_printk("TEMP_COMP_RANGE[%u] : [%d, %d], val : [%d]\r\n", i,
170             CMU_XO_TRIM_TEMP_LOW + i * CMU_XO_TRIM_TEMP_GAP, CMU_XO_TRIM_TEMP_LOW + (i + 1) * CMU_XO_TRIM_TEMP_GAP,
171             g_nv_xo_trim_temp_fine_code[i]);
172     }
173     osal_printk("TEMP_COMP_RANGE[%u] : [%d, ~ ], val : [%d]\r\n", i,
174         CMU_XO_TRIM_TEMP_LOW + i * CMU_XO_TRIM_TEMP_GAP, g_nv_xo_trim_temp_fine_code[i]);
175 }
176 #endif