1 /** @file wlan_txpwrlimit_cfg.c
2  *
3  *  @brief  This file provides WLAN World Wide Safe Mode Tx Power Limit APIs.
4  *
5  *  Copyright 2008-2024 NXP
6  *
7  *  SPDX-License-Identifier: BSD-3-Clause
8  *
9  */
10 
11 #include <wlan.h>
12 #include <wifi.h>
13 #ifdef RW610
14 #include "fsl_ocotp.h"
15 #endif
16 
17 #ifdef WIFI_BT_TX_PWR_LIMITS
18 #include WIFI_BT_TX_PWR_LIMITS
19 #else
20 #error "Region tx power config not defined"
21 #endif
22 
23 #if defined(RW610) && (CONFIG_COMPRESS_TX_PWTBL || ((CONFIG_COMPRESS_RU_TX_PWTBL) && (CONFIG_11AX)))
24 typedef struct _rg_power_info
25 {
26     t_u8 *rg_power_table;
27     t_u16 rg_len;
28 } rg_power_info;
29 #endif
30 
31 #if defined(RW610) && ((CONFIG_COMPRESS_RU_TX_PWTBL) && (CONFIG_11AX))
32 
33 typedef struct _ru_power_cfg
34 {
35     t_u16 region_code;
36     rg_power_info power_info;
37 } ru_power_cfg;
38 
39 /* All type boards ru txpwr data is same, */
40 ru_power_cfg ru_power_cfg_rw610[] = {
41     {0x00, .power_info = {(t_u8 *)rutxpowerlimit_cfg_set_WW, sizeof(rutxpowerlimit_cfg_set_WW)}},
42     {0x10, .power_info = {(t_u8 *)rutxpowerlimit_cfg_set_FCC, sizeof(rutxpowerlimit_cfg_set_FCC)}},
43     {0x30, .power_info = {(t_u8 *)rutxpowerlimit_cfg_set_EU, sizeof(rutxpowerlimit_cfg_set_EU)}},
44     {0x50, .power_info = {(t_u8 *)rutxpowerlimit_cfg_set_CN, sizeof(rutxpowerlimit_cfg_set_CN)}},
45     {0xFF, .power_info = {(t_u8 *)rutxpowerlimit_cfg_set_JP, sizeof(rutxpowerlimit_cfg_set_JP)}},
46 };
47 
wlan_set_ru_power_cfg(t_u16 region_code)48 int wlan_set_ru_power_cfg(t_u16 region_code)
49 {
50     int i  = 0;
51     int rv = -WM_FAIL;
52 
53     for (i = 0; i < sizeof(ru_power_cfg_rw610) / sizeof(ru_power_cfg); i++)
54     {
55         if (region_code == ru_power_cfg_rw610[i].region_code)
56         {
57             rv = wlan_set_11ax_rutxpowerlimit(ru_power_cfg_rw610[i].power_info.rg_power_table,
58                                               ru_power_cfg_rw610[i].power_info.rg_len);
59 
60             return rv;
61         }
62     }
63 
64     /* Set default world wide ru txpwr if ru_power_cfg_rw610 does not have a corresponding region_code temporarily */
65     wlcm_d("power_info of region_code %d not available, use default world wide ru txpwr by default.", region_code);
66 
67     rv = wlan_set_11ax_rutxpowerlimit(ru_power_cfg_rw610[0].power_info.rg_power_table,
68                                       ru_power_cfg_rw610[0].power_info.rg_len);
69 
70     return rv;
71 }
72 #endif
73 
74 #if defined(RW610) && (CONFIG_COMPRESS_TX_PWTBL)
75 #define MAX_SOC_OTP_LINE 64
76 #define OTP_PKG_TAG      0x15D
77 #define PKG_TYPE_MAX     3
78 
79 typedef struct _rg_power_cfg
80 {
81     t_u16 region_code;
82     rg_power_info power_info[PKG_TYPE_MAX];
83 } rg_power_cfg;
84 
85 /* For CSP board, we didn't get tx_power_table data, so use bga data temporary
86  * And maybe no BGA or QFN data for avaliable region, use other type data
87  */
88 rg_power_cfg rg_power_cfg_rw610[] = {
89     {0x10, .power_info[RW610_PACKAGE_TYPE_QFN] = {(t_u8 *)rg_rw610_qfn, sizeof(rg_rw610_qfn)},
90      .power_info[RW610_PACKAGE_TYPE_CSP] = {(t_u8 *)rg_rw610_csp, sizeof(rg_rw610_csp)},
91      .power_info[RW610_PACKAGE_TYPE_BGA] = {(t_u8 *)rg_rw610_bga, sizeof(rg_rw610_bga)}},
92     {0x30, .power_info[RW610_PACKAGE_TYPE_QFN] = {(t_u8 *)rg_rw610_EU, sizeof(rg_rw610_EU)},
93      .power_info[RW610_PACKAGE_TYPE_CSP] = {(t_u8 *)rg_rw610_EU, sizeof(rg_rw610_EU)},
94      .power_info[RW610_PACKAGE_TYPE_BGA] = {(t_u8 *)rg_rw610_EU, sizeof(rg_rw610_EU)}},
95     {0x40, .power_info[RW610_PACKAGE_TYPE_QFN] = {(t_u8 *)rg_rw610_JP, sizeof(rg_rw610_JP)},
96      .power_info[RW610_PACKAGE_TYPE_CSP] = {(t_u8 *)rg_rw610_JP, sizeof(rg_rw610_JP)},
97      .power_info[RW610_PACKAGE_TYPE_BGA] = {(t_u8 *)rg_rw610_JP, sizeof(rg_rw610_JP)}},
98     {0x50, .power_info[RW610_PACKAGE_TYPE_QFN] = {(t_u8 *)rg_rw610_CA, sizeof(rg_rw610_CA)},
99      .power_info[RW610_PACKAGE_TYPE_CSP] = {(t_u8 *)rg_rw610_CA, sizeof(rg_rw610_CA)},
100      .power_info[RW610_PACKAGE_TYPE_BGA] = {(t_u8 *)rg_rw610_CA, sizeof(rg_rw610_CA)}},
101     {0xFF, .power_info[RW610_PACKAGE_TYPE_QFN] = {(t_u8 *)rg_rw610_JP, sizeof(rg_rw610_JP)},
102      .power_info[RW610_PACKAGE_TYPE_CSP] = {(t_u8 *)rg_rw610_JP, sizeof(rg_rw610_JP)},
103      .power_info[RW610_PACKAGE_TYPE_BGA] = {(t_u8 *)rg_rw610_JP, sizeof(rg_rw610_JP)}},
104 };
105 
wlan_set_rg_power_cfg(t_u16 region_code)106 int wlan_set_rg_power_cfg(t_u16 region_code)
107 {
108     int i               = 0;
109     uint32_t board_type = 0;
110     int rv              = WM_SUCCESS;
111 
112     board_type = wifi_get_board_type();
113     if (RW610_PACKAGE_TYPE_QFN == board_type)
114     {
115         (void)PRINTF("PKG_TYPE: QFN\r\n");
116         (void)PRINTF("Set QFN tx power table data \r\n");
117     }
118     else if (RW610_PACKAGE_TYPE_BGA == board_type)
119     {
120         (void)PRINTF("PKG_TYPE: BGA\r\n");
121         (void)PRINTF("Set BGA tx power table data \r\n");
122     }
123     else if (RW610_PACKAGE_TYPE_CSP == board_type)
124     {
125         (void)PRINTF("PKG_TYPE: CSP\r\n");
126         (void)PRINTF("Set CSP tx power table data \r\n");
127     }
128     else
129     {
130         board_type = RW610_PACKAGE_TYPE_BGA;
131         (void)PRINTF("PKG_TYPE: UNKNOWN\r\n");
132         (void)PRINTF("Set BGA tx power table data \r\n");
133         (void)PRINTF("Can't get board type, we use bga data default \r\n");
134     }
135 
136     for (i = 0; i < sizeof(rg_power_cfg_rw610) / sizeof(rg_power_cfg); i++)
137     {
138         if (region_code == rg_power_cfg_rw610[i].region_code)
139         {
140             rv = wlan_set_region_power_cfg(rg_power_cfg_rw610[i].power_info[board_type].rg_power_table,
141                                            rg_power_cfg_rw610[i].power_info[board_type].rg_len);
142 
143             return rv;
144         }
145     }
146 
147     /* Set FCC power table if rg_power_cfg_rw610 does not have a corresponding region_code temporarily */
148     wlcm_d("power_info of region_code %d not available, use US power table by default.", region_code);
149 
150     rv = wlan_set_region_power_cfg(rg_power_cfg_rw610[0].power_info[board_type].rg_power_table,
151                                    rg_power_cfg_rw610[0].power_info[board_type].rg_len);
152 
153     return rv;
154 }
155 #elif (CONFIG_COMPRESS_TX_PWTBL)
156 typedef struct _rg_power_cfg
157 {
158     t_u16 region_code;
159     t_u8 *rg_power_table;
160     t_u16 rg_len;
161 } rg_power_cfg;
162 
163 rg_power_cfg rg_power_cfg_FC[] = {
164     {
165         0x00,
166         (t_u8 *)rg_table_fc,
167         sizeof(rg_table_fc),
168     },
169 };
170 
wlan_set_rg_power_cfg(t_u16 region_code)171 int wlan_set_rg_power_cfg(t_u16 region_code)
172 {
173     int i  = 0;
174     int rv = WM_SUCCESS;
175 
176     for (i = 0; i < sizeof(rg_power_cfg_FC) / sizeof(rg_power_cfg); i++)
177     {
178         if (region_code == rg_power_cfg_FC[i].region_code)
179         {
180             rv = wlan_set_region_power_cfg(rg_power_cfg_FC[i].rg_power_table, rg_power_cfg_FC[i].rg_len);
181             if (rv != WM_SUCCESS)
182                 (void)PRINTF("Unable to set compressed TX power table configuration\r\n");
183             return rv;
184         }
185     }
186 
187     return -WM_FAIL;
188 }
189 
190 #endif
191 
192 #if CONFIG_COMPRESS_TX_PWTBL
wlan_set_wwsm_txpwrlimit()193 int wlan_set_wwsm_txpwrlimit()
194 {
195     int rv = WM_SUCCESS;
196 #ifdef WLAN_REGION_CODE
197     rv = wlan_set_country_code(WLAN_REGION_CODE);
198     if (rv != WM_SUCCESS)
199     {
200         (void)PRINTF("Unable to set country code\r\n");
201         return -WM_FAIL;
202     }
203 #endif
204 #ifdef RW610
205     unsigned int region_code = 0;
206 #endif
207 #ifdef WLAN_REGION_CODE
208     rv = wlan_set_country_code(WLAN_REGION_CODE);
209     if (rv != WM_SUCCESS)
210     {
211         (void)PRINTF("Unable to set country code\r\n");
212         return -WM_FAIL;
213     }
214 #endif
215 #ifdef RW610
216     ARG_UNUSED(tx_pwrlimit_2g_cfg);
217     ARG_UNUSED(chanlist_2g_cfg);
218 #if CONFIG_5GHz_SUPPORT
219     ARG_UNUSED(tx_pwrlimit_5g_cfg);
220     ARG_UNUSED(chanlist_5g_cfg);
221 #endif
222 #endif
223 #ifndef RW610
224     rv = wlan_set_chanlist(&chanlist_2g_cfg);
225     if (rv != WM_SUCCESS)
226     {
227         (void)PRINTF("Unable to set 2G chanlist configuration\r\n");
228         return -WM_FAIL;
229     }
230 #if CONFIG_5GHz_SUPPORT
231     rv = wlan_set_chanlist(&chanlist_5g_cfg);
232     if (rv != WM_SUCCESS)
233     {
234         (void)PRINTF("Unable to set 5G chanlist configuration\r\n");
235         return -WM_FAIL;
236     }
237 #endif
238 #endif
239 #ifdef RW610
240     wlan_get_region_code(&region_code);
241     rv = wlan_set_rg_power_cfg(region_code);
242 #if (CONFIG_COMPRESS_RU_TX_PWTBL) && (CONFIG_11AX)
243     rv = wlan_set_ru_power_cfg(region_code);
244     if (rv != WM_SUCCESS)
245     {
246         return -WM_FAIL;
247     }
248 #endif
249 #else
250     rv = wlan_set_region_power_cfg(rg_table_fc, rg_table_fc_len);
251 #endif
252     if (rv != WM_SUCCESS)
253     {
254         (void)PRINTF("Unable to set compressed TX power table configuration\r\n");
255         return -WM_FAIL;
256     }
257 #ifndef RW610
258 #if CONFIG_11AX
259 #if CONFIG_COMPRESS_RU_TX_PWTBL
260     rv = wlan_set_11ax_rutxpowerlimit(rutxpowerlimit_cfg_set, sizeof(rutxpowerlimit_cfg_set));
261     if (rv != WM_SUCCESS)
262     {
263         (void)PRINTF("Unable to set RU TX PWR Limit configuration\r\n");
264         return -WM_FAIL;
265     }
266 #else
267     rv = wlan_set_11ax_rutxpowerlimit_legacy(&rutxpowerlimit_2g_cfg_set);
268     if (rv != WM_SUCCESS)
269     {
270         (void)PRINTF("Unable to set 2G RU TX PWR Limit configuration\r\n");
271         return -WM_FAIL;
272     }
273 #if CONFIG_5GHz_SUPPORT
274     else
275     {
276         rv = wlan_set_11ax_rutxpowerlimit_legacy(&rutxpowerlimit_5g_cfg_set);
277         if (rv != WM_SUCCESS)
278         {
279             (void)PRINTF("Unable to set 5G RU TX PWR Limit configuration\r\n");
280             return -WM_FAIL;
281         }
282     }
283 #endif
284 #endif /* CONFIG_COMPRESS_RU_TX_PWTBL */
285 #endif /* CONFIG_11AX */
286 #endif /* RW610 */
287 
288     return rv;
289 }
290 #else
wlan_set_wwsm_txpwrlimit(void)291 int wlan_set_wwsm_txpwrlimit(void)
292 {
293     int rv = WM_SUCCESS;
294 #ifdef WLAN_REGION_CODE
295     rv     = wlan_set_country_code(WLAN_REGION_CODE);
296     if (rv != WM_SUCCESS)
297     {
298         (void)PRINTF("Unable to set country code\r\n");
299         return -WM_FAIL;
300     }
301 #endif
302     rv = wlan_set_chanlist_and_txpwrlimit(&chanlist_2g_cfg, &tx_pwrlimit_2g_cfg);
303     if (rv != WM_SUCCESS)
304     {
305         (void)PRINTF("Unable to set 2G TX PWR Limit configuration\r\n");
306         return -WM_FAIL;
307     }
308 #if CONFIG_5GHz_SUPPORT
309     rv = wlan_set_chanlist_and_txpwrlimit(&chanlist_5g_cfg, &tx_pwrlimit_5g_cfg);
310     if (rv != WM_SUCCESS)
311     {
312         (void)PRINTF("Unable to set 5G TX PWR Limit configuration\r\n");
313         return -WM_FAIL;
314     }
315 #endif
316 
317 #ifndef RW610
318 #if CONFIG_11AX
319 #if CONFIG_COMPRESS_RU_TX_PWTBL
320     rv = wlan_set_11ax_rutxpowerlimit(rutxpowerlimit_cfg_set, sizeof(rutxpowerlimit_cfg_set));
321     if (rv != WM_SUCCESS)
322     {
323         (void)PRINTF("Unable to set RU TX PWR Limit configuration\r\n");
324         return -WM_FAIL;
325     }
326 #else
327     rv = wlan_set_11ax_rutxpowerlimit_legacy(&rutxpowerlimit_2g_cfg_set);
328     if (rv != WM_SUCCESS)
329     {
330         (void)PRINTF("Unable to set 2G RU TX PWR Limit configuration\r\n");
331         return -WM_FAIL;
332     }
333 #if CONFIG_5GHz_SUPPORT
334     else
335     {
336         rv = wlan_set_11ax_rutxpowerlimit_legacy(&rutxpowerlimit_5g_cfg_set);
337         if (rv != WM_SUCCESS)
338         {
339             (void)PRINTF("Unable to set 5G RU TX PWR Limit configuration\r\n");
340             return -WM_FAIL;
341         }
342     }
343 #endif
344 #endif /* CONFIG_COMPRESS_RU_TX_PWTBL */
345 #endif /* CONFIG_11AX */
346 #endif /* RW610 */
347 
348     return rv;
349 }
350 #endif /* CONFIG_COMPRESS_TX_PWTBL */
351 
352 #ifndef RW610
wlan_get_wlan_region_code(void)353 const char *wlan_get_wlan_region_code(void)
354 {
355 #ifdef WLAN_REGION_CODE
356     return WLAN_REGION_CODE;
357 #else
358 #error "Please define WLAN_REGION_CODE in Region tx power config file"
359 #endif
360 }
361 #endif
362