From 7486028dabcbd140343868e7b0c6eb19788cc384 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 21 Jul 2021 03:29:06 -0500 Subject: [PATCH 001/148] ignore build folder --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/build From 39ab9ce9c5af51ce8d1f6e058f907fafc625d75a Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 21 Jul 2021 03:30:05 -0500 Subject: [PATCH 002/148] Plan: replace object files in libbl602_wifi one by one --- CMakeLists.txt | 12 ++++++ src/bl602_wifi/CMakeLists.txt | 27 +++++++++++++ src/bl602_wifi/phy_bl602.c | 71 +++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 src/bl602_wifi/CMakeLists.txt create mode 100644 src/bl602_wifi/phy_bl602.c diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..5c60843 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.14.0) +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR riscv) +SET(CMAKE_CROSSCOMPILING 1) +set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") + + +project(bl602_re VERSION 0.1.0) + +include_directories(./src/include) + +add_subdirectory(./src/bl602_wifi) diff --git a/src/bl602_wifi/CMakeLists.txt b/src/bl602_wifi/CMakeLists.txt new file mode 100644 index 0000000..3a5e008 --- /dev/null +++ b/src/bl602_wifi/CMakeLists.txt @@ -0,0 +1,27 @@ + + +file(GLOB bl602_wifi_original_OBJs +"${PROJECT_SOURCE_DIR}/libbl602_wifi/*.o" +) + +file(GLOB bl602_wifi_SRCs +"*.c" +) + +foreach(blsrc ${bl602_wifi_SRCs}) + get_filename_component(wle ${blsrc} NAME_WLE) + list(APPEND NEEDREMOVE ${wle}) +endforeach() + +foreach(blobj ${bl602_wifi_original_OBJs}) + get_filename_component(wle ${blobj} NAME_WLE) + list(APPEND bl602_wifi_OBJs ${wle}) +endforeach() + +list(REMOVE_ITEM bl602_wifi_OBJs ${NEEDREMOVE}) +list(TRANSFORM bl602_wifi_OBJs PREPEND "${PROJECT_SOURCE_DIR}/libbl602_wifi/") +list(TRANSFORM bl602_wifi_OBJs APPEND ".o") + + +add_library(bl602_wifi STATIC ${bl602_wifi_SRCs} ${bl602_wifi_OBJs}) + diff --git a/src/bl602_wifi/phy_bl602.c b/src/bl602_wifi/phy_bl602.c new file mode 100644 index 0000000..027d385 --- /dev/null +++ b/src/bl602_wifi/phy_bl602.c @@ -0,0 +1,71 @@ +#include +#include +#include + +struct phy_bl602_cfg_tag { + uint32_t reserved; +}; // :48:8 + +struct phy_channel_info +{ + /// PHY channel information 1 + uint32_t info1; + /// PHY channel information 2 + uint32_t info2; +}; + +struct phy_env_tag { + struct phy_bl602_cfg_tag cfg; + uint16_t chnl_prim20_freq; + uint16_t chnl_center1_freq; + uint16_t chnl_center2_freq; + uint8_t band; + uint8_t chnl_type; +}; // :54:8 + +struct phy_env_tag phy_env[1]; // :75:20 +static int8_t rxgain_offset_vs_temperature; // :79:15 +static int8_t poweroffset[14]; // :80:15 + +void phy_config_rxgain(int offset) { + if (rxgain_offset_vs_temperature != offset) { + rxgain_offset_vs_temperature = (int8_t) offset; + AGC->rxgain_offset_vs_temperature[0] = (int)rxgain_offset_vs_temperature + 3; + AGC->rxgain_offset_vs_temperature[1] = (int)rxgain_offset_vs_temperature + 11; + AGC->rxgain_offset_vs_temperature[2] = (int)rxgain_offset_vs_temperature + 18; + AGC->rxgain_offset_vs_temperature[3] = (int)rxgain_offset_vs_temperature + 25; + AGC->rxgain_offset_vs_temperature[4] = (int)rxgain_offset_vs_temperature + 32; + AGC->rxgain_offset_vs_temperature[5] = (int)rxgain_offset_vs_temperature + 39; + AGC->rxgain_offset_vs_temperature[6] = (int)rxgain_offset_vs_temperature + 45; + AGC->rxgain_offset_vs_temperature[7] = (int)rxgain_offset_vs_temperature + 53; + AGC->rxgain_offset_vs_temperature[8] = (int)rxgain_offset_vs_temperature + 59; + } +} + +void phy_get_channel(struct phy_channel_info *info, uint8_t index) { + info->info1 = (uint32_t)phy_env[0].chnl_type << 8 | (uint32_t)phy_env[0].chnl_prim20_freq << 16 | + (uint32_t)phy_env[0].band; + info->info2 = phy_env[0].chnl_center1_freq | ((uint32_t)phy_env[0].chnl_center2_freq << 16); +} + +uint8_t phy_get_mac_freq(void) { + return 0x28; +} + +uint8_t phy_get_nss(void) { + return (uint8_t)(( (int8_t)(MDM->version.nss & 0xf) )- 1); +} + +void phy_get_version(uint32_t *version_1,uint32_t *version_2) { + *version_1 = MDM->version.value; + *version_2 = 0; + return; +} + +void agc_config(void) { + AGC->RWNXAGCCNTL.set_0x0_0 = 0; + AGC->RWNXAGCCNTL.set_0x0_1 = 0; + AGC->r0xb3a4.set_0x0_2 = 0; + AGC->r0xb3a4.set_0x0_3 = 0; + +} From d17771e34c7ed81c603f7e22f6d24c4fc8385740 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 21 Jul 2021 03:36:24 -0500 Subject: [PATCH 003/148] return field after added --- script/reglib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/reglib.py b/script/reglib.py index b2fb4ce..9e4d505 100755 --- a/script/reglib.py +++ b/script/reglib.py @@ -281,7 +281,7 @@ def Goto(addr): def Field(name, mask): if context.r: - context.r.addField(name, mask) + return context.r.addField(name, mask) else: print("You are not in any register") From 80db0accad7894cc0a64ca2ac50bdf53da08ca34 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 21 Jul 2021 04:02:26 -0500 Subject: [PATCH 004/148] add more reg from phy_bl602.o --- script/manualext.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/script/manualext.py b/script/manualext.py index 96adaf8..80781ee 100755 --- a/script/manualext.py +++ b/script/manualext.py @@ -13,7 +13,6 @@ Field('vht', 0xfffffffd) # very high throughput Field('v31', 0xfffeffff) # some switch? DAT_44c00000>>31 - Reg('rxchan', 0x44c00820) Field('rxcbwmax', 0xfcffffff) # Channel bandwidth Field('rxnssmax', 0xffffff8f) # number of spatial streams @@ -29,11 +28,14 @@ FieldBit('rxndpnstsmax', 0xc, 4) FieldBit('v18', 0x12) FieldBit('v19', 0x13) -FieldBit('v30', 0x1e) -FieldBit('v31', 0x1f) +FieldBit('mu_mimo_rx', 0x1e) +FieldBit('mu_mimo_tx', 0x1f) FieldBit('ldpctx', 0x1a) +FieldBit('ldpcrx', 0x1b) FieldBit('ntx', 4, 4) # phy_get_ntx (ntx + 1) FieldBit('txcbwmax', 0x18, 2) +FieldBit('bfmee_supported', 0x1c) +FieldBit('bfmer_supported', 0x1d) Reg('mdmconf', 0x44c00800) From fed3a5aaa58d91dd88eb40e0276181ebc802c416 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 21 Jul 2021 04:03:31 -0500 Subject: [PATCH 005/148] update mdm.h with regs found in phy_bl602.o --- src/include/phy/mdm.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/include/phy/mdm.h b/src/include/phy/mdm.h index a57d99b..9ce4863 100644 --- a/src/include/phy/mdm.h +++ b/src/include/phy/mdm.h @@ -17,9 +17,11 @@ typedef union { uint32_t pad3 : 1; uint32_t txcbwmax : 2; // @ 25 -- 24 # 0xfcffffff uint32_t ldpctx : 1; // @ 26 -- 26 # 0xfbffffff - uint32_t pad4 : 3; - uint32_t v30 : 1; // @ 30 -- 30 # 0xbfffffff - uint32_t v31 : 1; // @ 31 -- 31 # 0x7fffffff + uint32_t ldpcrx : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t bfmee_supported : 1; // @ 28 -- 28 # 0xefffffff + uint32_t bfmer_supported : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t mu_mimo_rx : 1; // @ 30 -- 30 # 0xbfffffff + uint32_t mu_mimo_tx : 1; // @ 31 -- 31 # 0x7fffffff }; } version; // @ 0x0 uint8_t pad0[0x7fc]; From 8898ba599e2b1b045c21537970d0e4c79d5a60e9 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 21 Jul 2021 05:11:03 -0500 Subject: [PATCH 006/148] add missing bit --- script/manualext.py | 1 + 1 file changed, 1 insertion(+) diff --git a/script/manualext.py b/script/manualext.py index 80781ee..2a182fd 100755 --- a/script/manualext.py +++ b/script/manualext.py @@ -21,6 +21,7 @@ Field('vht', 0xfffffffd) # very high throughput Field('v30', 0xfffeffff) # some switch? DAT_44c00000>>30 Field('_v30', 0xffefffff) # some switch? DAT_44c00000>>30 +FieldBit('reset', 0) # set 1 in phy_hw_set_channel for.. reset? Reg('version', 0x44c00000) FieldBit('vht', 31-9) From 2a14d5a1ddb74841275195f182ba2603a2e6e0be Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 21 Jul 2021 05:11:19 -0500 Subject: [PATCH 007/148] add bit --- src/include/phy/mdm.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/include/phy/mdm.h b/src/include/phy/mdm.h index 9ce4863..ebb7e60 100644 --- a/src/include/phy/mdm.h +++ b/src/include/phy/mdm.h @@ -49,17 +49,17 @@ typedef union { union { uint32_t value; struct { - uint32_t pad0 : 1; + uint32_t reset : 1; // @ 0 -- 0 # 0xfffffffe uint32_t vht : 1; // @ 1 -- 1 # 0xfffffffd - uint32_t pad1 : 2; + uint32_t pad0 : 2; uint32_t rxnssmax : 3; // @ 6 -- 4 # 0xffffff8f - uint32_t pad2 : 1; + uint32_t pad1 : 1; uint32_t v19 : 1; // @ 8 -- 8 # 0xfffffeff - uint32_t pad3 : 7; + uint32_t pad2 : 7; uint32_t v30 : 1; // @ 16 -- 16 # 0xfffeffff - uint32_t pad4 : 3; + uint32_t pad3 : 3; uint32_t _v30 : 1; // @ 20 -- 20 # 0xffefffff - uint32_t pad5 : 3; + uint32_t pad4 : 3; uint32_t rxcbwmax : 2; // @ 25 -- 24 # 0xfcffffff }; } rxchan; // @ 0x820 From b778274b6f628e3a810eaacdcb1b7c183399a7fa Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 21 Jul 2021 05:47:51 -0500 Subject: [PATCH 008/148] add missing rxndpnstsmax --- script/manualext.py | 1 + src/include/phy/mdm.h | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/script/manualext.py b/script/manualext.py index 2a182fd..9dc38ac 100755 --- a/script/manualext.py +++ b/script/manualext.py @@ -22,6 +22,7 @@ Field('v30', 0xfffeffff) # some switch? DAT_44c00000>>30 Field('_v30', 0xffefffff) # some switch? DAT_44c00000>>30 FieldBit('reset', 0) # set 1 in phy_hw_set_channel for.. reset? +Field('rxndpnstsmax', 0xffff8fff) Reg('version', 0x44c00000) FieldBit('vht', 31-9) diff --git a/src/include/phy/mdm.h b/src/include/phy/mdm.h index ebb7e60..8bdd17f 100644 --- a/src/include/phy/mdm.h +++ b/src/include/phy/mdm.h @@ -55,11 +55,13 @@ typedef union { uint32_t rxnssmax : 3; // @ 6 -- 4 # 0xffffff8f uint32_t pad1 : 1; uint32_t v19 : 1; // @ 8 -- 8 # 0xfffffeff - uint32_t pad2 : 7; + uint32_t pad2 : 3; + uint32_t rxndpnstsmax : 3; // @ 14 -- 12 # 0xffff8fff + uint32_t pad3 : 1; uint32_t v30 : 1; // @ 16 -- 16 # 0xfffeffff - uint32_t pad3 : 3; - uint32_t _v30 : 1; // @ 20 -- 20 # 0xffefffff uint32_t pad4 : 3; + uint32_t _v30 : 1; // @ 20 -- 20 # 0xffefffff + uint32_t pad5 : 3; uint32_t rxcbwmax : 2; // @ 25 -- 24 # 0xfcffffff }; } rxchan; // @ 0x820 From 427e66d192e82e1ab654377ddd7c9dd9c3544c1f Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 21 Jul 2021 06:35:36 -0500 Subject: [PATCH 009/148] generate agc code automatically --- script/manualext.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/script/manualext.py b/script/manualext.py index 9dc38ac..f81e071 100755 --- a/script/manualext.py +++ b/script/manualext.py @@ -159,11 +159,15 @@ def scan_write(code): name_f = f'set_{hex(value)}_{gid}' name_r = f'r{hex(addr&0xffff)}' gid = gid + 1 - Reg(name_r, addr) - Field(name_f, mask) - -scan_write(open('../blobs/agc_config.c').readlines()) -scan_write([ + r = Reg(name_r, addr) + f = Field(name_f, mask) + yield r.name, f.name, value + +print("agc_config") +for rn, fn, val in scan_write(open('../blobs/agc_config.c').readlines()): + print(f"AGC->{rn}.{fn} = {hex(val)}") +print("ex") +for rn, fn, val in scan_write([ "write_volatile_4(DAT_44c0c020,uVar4 & 0xfc00ffff | 0x140000);", "write_volatile_4(DAT_44c0b390,uVar1 & 0xfffffeff);", "write_volatile_4(DAT_44c0b500,uVar4 & 0xffffcfff | 0x2000);", @@ -171,7 +175,8 @@ def scan_write(code): "write_volatile_4(DAT_44c0b110,uVar4 & 0xfffffffb);", "write_volatile_4(DAT_44c0b110,uVar4 & 0xfffffffd);", "write_volatile_4(DAT_44c0b110,uVar4 & 0xfffffffe);", -]) +]): + print(f"AGC->{rn}.{fn} = {hex(val)}") open('../src/include/phy/agc.h', 'w').write('\n'.join(GenHeader())) #print('\n'.join(GenHeader())) #print('\n'.join(GenSVD())) From 1eda44aa7fc7c170e19c6b80281d86aa85970229 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 21 Jul 2021 06:36:09 -0500 Subject: [PATCH 010/148] add used functions in header --- src/bl602_wifi/phy_adapt.h | 6 ++++ src/bl602_wifi/phy_bl602.h | 65 ++++++++++++++++++++++++++++++++++++++ src/bl602_wifi/phy_tcal.h | 6 ++++ src/bl602_wifi/phy_trpc.h | 9 ++++++ src/bl602_wifi/rf.h | 4 +++ src/bl602_wifi/rfc_bl602.h | 5 +++ 6 files changed, 95 insertions(+) create mode 100644 src/bl602_wifi/phy_adapt.h create mode 100644 src/bl602_wifi/phy_bl602.h create mode 100644 src/bl602_wifi/phy_tcal.h create mode 100644 src/bl602_wifi/phy_trpc.h create mode 100644 src/bl602_wifi/rf.h create mode 100644 src/bl602_wifi/rfc_bl602.h diff --git a/src/bl602_wifi/phy_adapt.h b/src/bl602_wifi/phy_adapt.h new file mode 100644 index 0000000..4de482b --- /dev/null +++ b/src/bl602_wifi/phy_adapt.h @@ -0,0 +1,6 @@ +#ifndef _PHY_ADAPT_H_ +#define _PHY_ADAPT_H_ +void pa_adapt(void); +void pa_init(void); +void pa_input(void); +#endif \ No newline at end of file diff --git a/src/bl602_wifi/phy_bl602.h b/src/bl602_wifi/phy_bl602.h new file mode 100644 index 0000000..c0758f3 --- /dev/null +++ b/src/bl602_wifi/phy_bl602.h @@ -0,0 +1,65 @@ +#ifndef _PHY_BL602_H_ +#include + +enum +{ + /// 2.4GHz Band + PHY_BAND_2G4, + /// 5GHz band + PHY_BAND_5G, + /// Number of bands + PHY_BAND_MAX, +}; + +enum +{ + PHY_CHNL_BW_20, + PHY_CHNL_BW_40, + PHY_CHNL_BW_80, + PHY_CHNL_BW_160, + PHY_CHNL_BW_80P80, + PHY_CHNL_BW_OTHER, +}; + +struct phy_channel_info +{ + /// PHY channel information 1 + uint32_t info1; + /// PHY channel information 2 + uint32_t info2; +}; + +typedef struct phy_cfg_tag phy_cfg_tag; + +struct phy_cfg_tag { + uint32_t parameters[16]; +}; + + +struct phy_bl602_cfg_tag { + uint32_t reserved; +}; // :48:8 + +struct phy_env_tag { + struct phy_bl602_cfg_tag cfg; + uint16_t chnl_prim20_freq; + uint16_t chnl_center1_freq; + uint16_t chnl_center2_freq; + uint8_t band; + uint8_t chnl_type; +}; // :54:8 +struct phy_env_tag phy_env[1]; // :75:20 + +void phy_config_rxgain(int offset); +uint8_t phy_get_mac_freq(); +void phy_get_channel(struct phy_channel_info *info, uint8_t index); +uint8_t phy_get_mac_freq(void); +uint8_t phy_get_nss(void); +void phy_get_version(uint32_t *version_1,uint32_t *version_2); +void agc_config(void); +void mdm_reset(); +void mpif_clk_init(void); +uint8_t phy_vht_supported(); +uint8_t phy_get_ntx(void); +uint8_t phy_get_nss(void); +#endif \ No newline at end of file diff --git a/src/bl602_wifi/phy_tcal.h b/src/bl602_wifi/phy_tcal.h new file mode 100644 index 0000000..87cb0c7 --- /dev/null +++ b/src/bl602_wifi/phy_tcal.h @@ -0,0 +1,6 @@ +#ifndef _PHY_TCAL_H_ +#define _PHY_TCAL_H_ +void phy_tcal_reset(void); +void phy_tcal_start(void); + +#endif \ No newline at end of file diff --git a/src/bl602_wifi/phy_trpc.h b/src/bl602_wifi/phy_trpc.h new file mode 100644 index 0000000..e4480d9 --- /dev/null +++ b/src/bl602_wifi/phy_trpc.h @@ -0,0 +1,9 @@ +#ifndef _PHY_TRPC_H_ +#define _PHY_TRPC_H_ +#include +void trpc_init(void); +int8_t trpc_get_rf_max_power(void); +int8_t trpc_get_rf_min_power(void); +uint8_t trpc_get_power_idx(uint8_t formatmod, uint8_t mcs, int8_t pwr_dbm); +void trpc_update_vs_channel(int8_t channel_MHz); // :171:6 +#endif \ No newline at end of file diff --git a/src/bl602_wifi/rf.h b/src/bl602_wifi/rf.h new file mode 100644 index 0000000..d73cf2d --- /dev/null +++ b/src/bl602_wifi/rf.h @@ -0,0 +1,4 @@ +#ifndef _RF_H_ +#define _RF_H_ +void rf_set_channel(uint8_t bandwidth, uint16_t channel_freq); +#endif \ No newline at end of file diff --git a/src/bl602_wifi/rfc_bl602.h b/src/bl602_wifi/rfc_bl602.h new file mode 100644 index 0000000..2387da6 --- /dev/null +++ b/src/bl602_wifi/rfc_bl602.h @@ -0,0 +1,5 @@ +#ifndef _RFC_BL602_H_ +#define _RFC_BL602_H_ +uint32_t rfc_get_power_level(uint32_t formatmod, int32_t power); // :1479:10 +void rfc_apply_tx_power_offset(uint8_t channel, int8_t *power_offset); // :1643:6 +#endif \ No newline at end of file From 2e9d77294aecb1ecbd6b715c4594bb8044adcfbc Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 21 Jul 2021 06:36:19 -0500 Subject: [PATCH 011/148] finish phy_bl602 --- src/bl602_wifi/phy_bl602.c | 325 ++++++++++++++++++++++++++++++++++--- 1 file changed, 299 insertions(+), 26 deletions(-) diff --git a/src/bl602_wifi/phy_bl602.c b/src/bl602_wifi/phy_bl602.c index 027d385..d7401b1 100644 --- a/src/bl602_wifi/phy_bl602.c +++ b/src/bl602_wifi/phy_bl602.c @@ -1,29 +1,23 @@ #include #include #include +#include + +#include "phy_bl602.h" +#include "phy_trpc.h" +#include "rfc_bl602.h" +#include "phy_adapt.h" +#include "phy_tcal.h" +#include "rf.h" + +void assert_err(char * condition, char * file, int line); + +#define ASSERT_ERR(cond) if (!(cond)) assert_err(#cond, __FILE__, __LINE__); + +#define PHY_FORMATMOD_11B 0 +#define PHY_FORMATMOD_11G 1 +#define PHY_FORMATMOD_11N 2 -struct phy_bl602_cfg_tag { - uint32_t reserved; -}; // :48:8 - -struct phy_channel_info -{ - /// PHY channel information 1 - uint32_t info1; - /// PHY channel information 2 - uint32_t info2; -}; - -struct phy_env_tag { - struct phy_bl602_cfg_tag cfg; - uint16_t chnl_prim20_freq; - uint16_t chnl_center1_freq; - uint16_t chnl_center2_freq; - uint8_t band; - uint8_t chnl_type; -}; // :54:8 - -struct phy_env_tag phy_env[1]; // :75:20 static int8_t rxgain_offset_vs_temperature; // :79:15 static int8_t poweroffset[14]; // :80:15 @@ -63,9 +57,288 @@ void phy_get_version(uint32_t *version_1,uint32_t *version_2) { } void agc_config(void) { - AGC->RWNXAGCCNTL.set_0x0_0 = 0; - AGC->RWNXAGCCNTL.set_0x0_1 = 0; - AGC->r0xb3a4.set_0x0_2 = 0; - AGC->r0xb3a4.set_0x0_3 = 0; + AGC->RWNXAGCCNTL.set_0x0_0 = 0x0; + AGC->RWNXAGCCNTL.set_0x0_1 = 0x0; + AGC->r0xb3a4.set_0x0_2 = 0x0; + AGC->r0xb3a4.set_0x0_3 = 0x0; + AGC->r0xb394.set_0xf8_4 = 0xf8; + AGC->r0xb398.set_0x9e_5 = 0x9e; + AGC->r0xb3c4.set_0xce_6 = 0xce; + AGC->r0xb364.set_0x8_7 = 0x8; + AGC->r0xb364.set_0x3c_8 = 0x3c; + AGC->r0xb364.set_0x38_9 = 0x38; + AGC->r0xb364.set_0x39_10 = 0x39; + AGC->r0xb368.set_0x70_11 = 0x70; + AGC->r0xb368.set_0x70_12 = 0x70; + AGC->r0xb36c.set_0x12_13 = 0x12; + AGC->r0xb36c.set_0x5_14 = 0x5; + AGC->r0xb36c.set_0x28_15 = 0x28; + AGC->r0xb36c.set_0x7_16 = 0x7; + AGC->r0xb370.set_0x58_17 = 0x58; + AGC->r0xb3c0.set_0x18_18 = 0x18; + AGC->r0xb380.set_0x3e_19 = 0x3e; + AGC->r0xb380.set_0x37_20 = 0x37; + AGC->r0xb380.set_0x1_21 = 0x1; + AGC->r0xb380.set_0x0_22 = 0x0; + AGC->r0xb380.set_0x1_23 = 0x1; + AGC->r0xb384.set_0x39_24 = 0x39; + AGC->r0xb384.set_0x37_25 = 0x37; + AGC->r0xb384.set_0x14_26 = 0x14; + AGC->r0xb384.set_0x0_27 = 0x0; + AGC->r0xb384.set_0x2_28 = 0x2; + AGC->r0xb388.set_0xf_29 = 0xf; + AGC->r0xb388.set_0x17_30 = 0x17; + AGC->r0xb388.set_0x2a_31 = 0x2a; + AGC->r0xb388.set_0x0_32 = 0x0; + AGC->r0xb388.set_0x5_33 = 0x5; + AGC->r0xb38c.set_0x19_34 = 0x19; + AGC->r0xb38c.set_0x0_35 = 0x0; + AGC->r0xb38c.set_0xe_36 = 0xe; + AGC->r0xb38c.set_0x2_37 = 0x2; + AGC->r0xc830.set_0x3f_38 = 0x3f; + AGC->r0xc830.set_0x1_39 = 0x1; + AGC->r0xc830.set_0x36_40 = 0x36; + AGC->r0xc830.set_0x5_41 = 0x5; + AGC->r0xc814.set_0x0_42 = 0x0; + AGC->r0xc040.set_0xc_43 = 0xc; + AGC->r0xc040.set_0x3_44 = 0x3; + AGC->r0xc044.set_0x8_45 = 0x8; + AGC->r0xc044.set_0x0_46 = 0x0; + + phy_config_rxgain(0); + + AGC->r0xb3a0.set_0x9e_47 = 0x9e; + AGC->r0xb3c0.set_0xa4_48 = 0xa4; + AGC->r0xb3c0.set_0xa3_49 = 0xa3; + AGC->r0xc82c.set_0xb5_50 = 0xb5; + AGC->r0xc82c.set_0x1_51 = 0x1; + AGC->r0xc82c.set_0x1_52 = 0x1; + AGC->r0xc838.set_0x1_53 = 0x1; + AGC->r0xc838.set_0x100_54 = 0x100; + AGC->r0xc83c.set_0x1_55 = 0x1; + AGC->r0xc83c.set_0x17c_56 = 0x17c; + AGC->r0xc840.set_0x1_57 = 0x1; + AGC->r0xc840.set_0x100_58 = 0x100; + AGC->r0xc82c.set_0x40_59 = 0x40; +} + +void bz_phy_reset(void) { + // UNUSED Function + return ; +} + +void mdm_reset() { + MDM->swreset.value = 0x1111; + MDM->swreset.value = 0x0; +} + +void mpif_clk_init(void) { + // Empty Function + return ; +} + +uint8_t phy_bfmee_supported() { + return MDM->version.bfmee_supported; +} + +uint8_t phy_bfmer_supported(void) { + return MDM->version.bfmer_supported; +} + +void phy_get_rf_gain_capab(int8_t *max,int8_t *min) { + *max = trpc_get_rf_max_power(); + *min = trpc_get_rf_min_power(); +} + +void phy_get_rf_gain_idx(int8_t *power,uint8_t *idx) { + *idx = (uint8_t)rfc_get_power_level(2, (int)*power * 10); +} + +void phy_get_rf_gain_idx_vs_mode(uint8_t mode,int8_t *power,uint8_t *idx){ + *idx = (uint8_t)rfc_get_power_level(mode, (int)*power * 10); +} + +void phy_get_trpc_idx(uint8_t formatmod,uint8_t mcs,int8_t power,uint8_t *idx) { + // THIS IS ONLY MY GUESS. THE REAL DISASSEMBLY LOOKS VERY WEIRD AND IT MUST BE WRONG + ASSERT_ERR(formatmod <= PHY_FORMATMOD_11N); + if (formatmod == PHY_FORMATMOD_11G) + ASSERT_ERR((formatmod == PHY_FORMATMOD_11G) && (mcs <= 7)); // lc9 + if (formatmod == PHY_FORMATMOD_11B) + ASSERT_ERR((formatmod == PHY_FORMATMOD_11B) && (mcs <= 3)); // lc10 + if (formatmod == PHY_FORMATMOD_11N) + ASSERT_ERR((formatmod == PHY_FORMATMOD_11N) && (mcs <= 7)); // lc11 + *idx = (uint8_t)trpc_get_power_idx(formatmod, mcs, power); +} + +void phy_powroffset_set(int8_t *power_offset) { + for (int i = 0; i < 14; i++) { + poweroffset[i] = power_offset[i]; + } +} + +int phy_freq_to_channel(uint8_t band, uint16_t freq); + +void phy_hw_set_channel(uint8_t band, uint16_t freq, uint16_t freq1, uint8_t chantype) { + ASSERT_ERR(chantype == PHY_CHNL_BW_20); + ASSERT_ERR(band == PHY_BAND_2G4); + AGC->RWNXAGCCNTL.set_0x0_61 = 0; + MDM->rxchan.reset = 1; + MDM->mdmconf = 0; + mdm_reset(); + MDM->TXCTRL0 = 0xb4; + MDM->TXCTRL1 = 0x1c13; + MDM->TXCTRL3 = 0x2d00438; + MDM->TBECTRL0.tbe_count_adjust_20 = 0; + MDM->DCESTIMCTRL.value = 0xf0f; + MDM->DCESTIMCTRL.WAITHTSTF = 7; + MDM->r834.set60h = 0x6; + MDM->SMOOTHCTRL.value = 0x1880c06; + MDM->tbectrl2 = 0x7f03; + AGC->riu_rwnxagcaci20marg0 = 0; + AGC->riu_rwnxagcaci20marg1 = 0; + AGC->riu_rwnxagcaci20marg2 = 0; + MDM->txchan.txcbwmax = chantype; + + if (AGC->r000.iqcomp) { + AGC->riu_iqestiterclr = 1; + } + + rf_set_channel(chantype,freq1); + + uint8_t channel = 0; + + /* + int iVar3 = 0; + if (band == PHY_BAND_2G4) { + if ((freq - 0x96cU & 0xffff) >= 0x48) { + channel = 0xe; + if (freq != 0x9b4) { + channel = (uint8_t)((freq -0x967) / 5); + } + } + + } + */ + // TODO: are these two functions equivelant??? + channel = phy_freq_to_channel(band, freq); + rfc_apply_tx_power_offset(channel, poweroffset); + trpc_update_vs_channel((int8_t)freq1); +} + +void phy_set_channel(uint8_t band,uint8_t type,uint16_t prim20_freq,uint16_t center1_freq, + uint16_t center2_freq,uint8_t index) { + if ((center1_freq >= 2412 && center1_freq <= 2484) || (band == PHY_BAND_5G)) { + phy_hw_set_channel(band,prim20_freq,center1_freq,type); + phy_env[0].chnl_prim20_freq = prim20_freq; + phy_env[0].chnl_center1_freq = center1_freq; + phy_env[0].band = band; + phy_env[0].chnl_type = type; + } +} + +extern uint32_t agcmem[]; + +void phy_init(phy_cfg_tag *config) { + MDM->mdmconf = 0; + mdm_reset(); + MDM->rxchan.value = 0x20d; + MDM->rxchan.rxnssmax = phy_get_nss(); + MDM->rxchan.rxndpnstsmax = MDM->version.rxndpnstsmax; + MDM->rxchan.v19 = MDM->version.v19; + MDM->rxchan.vht = phy_vht_supported(); + MDM->rxchan.v30 = MDM->version.mu_mimo_rx; + MDM->r3024.precomp = 0x2D; + MDM->rxframeviolationmask = 0xffffffff; + + MDM->txchan.value = 0x20d; + MDM->txchan.txnssmax = phy_get_nss(); + MDM->txchan.ntxmax = phy_get_ntx(); + MDM->txchan.txcbwmax = MDM->version.txcbwmax; + MDM->txchan.v18 = MDM->version.v18; + MDM->txchan.vht = phy_vht_supported(); + MDM->txchan.v31 = MDM->version.mu_mimo_tx; + + MDM->r834.set1 = 1; + MDM->SMOOTHCTRL.CFGSMOOTHFORCE = 0; + MDM->SMOOTHSNRTHR.smoothsnrthrhigh = 0x1b; + MDM->SMOOTHSNRTHR.smoothsnrthrmid = 0xf; + MDM->rxctrl1 = 0x4920492; + MDM->r874.resetto1 = 1; + + AGC->r0xb500.set_0x2_62 = 0x02; + if (AGC->r000.iqcomp) { + AGC->r0xb110.set_0x0_63 = 0; + AGC->r0xb110.set_0x0_64 = 0; + AGC->r0xb110.set_0x0_65 = 0; + AGC->r0xb110.set_0x0_66 = 0; + AGC->riu_iqestiterclr = 0; + } + AGC->activeant = 1; + AGC->RWNXAGCCNTL.set1 = 1; + AGC->RWNXAGCCCATIMEOUT = 4000000; + AGC->irqmacccatimeouten.set1 = 1; + agc_config(); + AGC->RWNXAGCCNTL.agcfsmreset = 1; + + MDM->r874.set1beforewriteagcmem = 1; + + for (int i = 0; i < 0x200; i++) + AGCRAM->agcram[i] = agcmem[i]; + + MDM->r874.set1beforewriteagcmem = 0; + AGC->RWNXAGCCNTL.agcfsmreset = 0; + AGC->r0xc020.set_0x14_60 = 0x14; + phy_env[0].cfg.reserved = (config->parameters)[0]; + phy_env[0].chnl_center1_freq = 0xff; + phy_env[0].chnl_center2_freq = 0xff; + phy_env[0].chnl_prim20_freq = 0xff; + phy_env[0].band = 0x00; + phy_env[0].chnl_type = PHY_CHNL_BW_OTHER; + trpc_init(); + pa_init(); + phy_tcal_reset(); + phy_tcal_start(); +} + +uint8_t phy_vht_supported(){ + if (MDM->version.vht) // TODO: verify this cond + return 1; + return ((MDM->version.txcbwmax) >> 1) & 1; +} + +uint8_t phy_ldpc_rx_supported(void){ + return MDM->version.ldpcrx; +} + +uint8_t phy_ldpc_tx_supported(void){ + return MDM->version.ldpctx; +} + +void phy_mdm_isr(void) { + return; +} + +uint8_t phy_mu_mimo_rx_supported(void) { + return MDM->version.mu_mimo_rx; +} + +uint8_t phy_mu_mimo_tx_supported(void) { + return MDM->version.mu_mimo_tx; +} + +void phy_rc_isr(void) { + uint32_t val = AGC->r41c.value; + AGC->r420_copy41c = val; + if (val & 0x100) { + mdm_reset(); + } +} + +void phy_reset(void) { + return ; +} + +void phy_stop(void){ + return ; } From d395b9aa985f7821cb9b7f222e37bc13e3703404 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 21 Jul 2021 19:14:14 -0500 Subject: [PATCH 012/148] support parse bl svd file and find reg with addr and mask --- script/manualext.py | 55 ++++++++++++++++++++++++++++----------------- script/reglib.py | 18 +++++++++++++++ script/svd2c.py | 45 +++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 21 deletions(-) create mode 100755 script/svd2c.py diff --git a/script/manualext.py b/script/manualext.py index f81e071..d407d0d 100755 --- a/script/manualext.py +++ b/script/manualext.py @@ -1,9 +1,12 @@ #!/usr/bin/env python3 from reglib import * +from typing import Mapping + +peris :Mapping[str, peripheral] = {} ############ MDM -Peripheral(peripheral('mdm', 0x44c00000, 0x4000)) +peris['mdm'] = Peripheral(peripheral('mdm', 0x44c00000, 0x4000)) Reg('txchan', 0x44c00824) Field('txcbwmax', 0xfcffffff) # Channel bandwidth @@ -92,16 +95,13 @@ Reg('r874', 0x44c00874) Field('resetto1', 0xf7ffffff) Field('set1beforewriteagcmem', 0xdfffffff) - -open('../src/include/phy/mdm.h', 'w').write('\n'.join(GenHeader())) #print('\n'.join(GenSVD())) ############# AGC - -Peripheral(peripheral('agc', 0x44c0b000, 0x2000)) +peris['agc'] = Peripheral(peripheral('agc', 0x44c0b000, 0x2000)) Reg('r000', 0x44c0b000) FieldBit('iqcomp', 31-10) @@ -177,15 +177,15 @@ def scan_write(code): "write_volatile_4(DAT_44c0b110,uVar4 & 0xfffffffe);", ]): print(f"AGC->{rn}.{fn} = {hex(val)}") -open('../src/include/phy/agc.h', 'w').write('\n'.join(GenHeader())) +#open('../src/include/phy/agc.h', 'w').write('\n'.join(GenHeader())) #print('\n'.join(GenHeader())) #print('\n'.join(GenSVD())) -Peripheral(peripheral('agcram', 0x54c0a000, 0x800)) +peris['agcram'] = Peripheral(peripheral('agcram', 0x54c0a000, 0x800)) Buf('agcram', 0x54c0a000, 0x54c0a800 - 4) -open('../src/include/phy/agcram.h', 'w').write('\n'.join(GenHeader())) +#open('../src/include/phy/agcram.h', 'w').write('\n'.join(GenHeader())) #print('\n'.join(GenHeader())) #print('\n'.join(GenSVD())) # @@ -220,23 +220,23 @@ def getregs(fname, pattern='name'): -Peripheral(peripheral('mac_core', 0x44b00000, 0x1000)) +peris['mac_core'] = Peripheral(peripheral('mac_core', 0x44b00000, 0x1000)) for code, offset in getregs("../components/bl602/bl602_wifidrv/bl60x_wifi_driver/reg_mac_core.h", pattern='brief'): RegFromComment(offset + 0x44b00000, code) -open('../src/include/phy/mac_core.h', 'w').write('\n'.join(GenHeader())) +#open('../src/include/phy/mac_core.h', 'w').write('\n'.join(GenHeader())) #print('\n'.join(GenHeader())) #print('\n'.join(GenSVD())) -Peripheral(peripheral('mac_pl', 0x44b08000, 0x1000)) +peris['mac_pl'] = Peripheral(peripheral('mac_pl', 0x44b08000, 0x1000)) for code, offset in getregs("../alios/mac_pl.h"): RegFromComment(offset + 0x44b00000, code) -open('../src/include/phy/mac_pl.h', 'w').write('\n'.join(GenHeader())) +#open('../src/include/phy/mac_pl.h', 'w').write('\n'.join(GenHeader())) #print('\n'.join(GenHeader())) #print('\n'.join(GenSVD())) @@ -247,7 +247,7 @@ def getregs(fname, pattern='name'): ## look txl_payload_handle_backup for more info #### -Peripheral(peripheral('dma', 0x44a00000, 0x1000)) +peris['dma'] = Peripheral(peripheral('dma', 0x44a00000, 0x1000)) Reg('status', 0x44a00024) Field("TX", 0x1f) @@ -283,13 +283,13 @@ def getregs(fname, pattern='name'): Reg('LinkListItem1', 0x44a000ac) FieldBit("lli", 0, 16) -open('../src/include/phy/dma.h', 'w').write('\n'.join(GenHeader())) +#open('../src/include/phy/dma.h', 'w').write('\n'.join(GenHeader())) #print('\n'.join(GenHeader())) #print('\n'.join(GenSVD())) ############# sysctrl -Peripheral(peripheral('sysctrl', 0x44900000, 0x1000)) +peris['sysctrl'] = Peripheral(peripheral('sysctrl', 0x44900000, 0x1000)) Reg('time', 0x44900084) FieldBit('time_greater_on_bit12', 0) Reg("sysctrl_r68", 0x44900068) # set to 0x8000000c for init @@ -303,7 +303,7 @@ def getregs(fname, pattern='name'): Reg("r074", 0x44900068) # set to b09 -open('../src/include/phy/sysctrl.h', 'w').write('\n'.join(GenHeader())) +#open('../src/include/phy/sysctrl.h', 'w').write('\n'.join(GenHeader())) #print('\n'.join(GenHeader())) #print('\n'.join(GenSVD())) @@ -311,20 +311,33 @@ def getregs(fname, pattern='name'): ############# Wifi Regs 92 ## wtf is this??? -Peripheral(peripheral('sysctrl92', 0x44920000, 0x1000)) +peris['sysctrl92'] = Peripheral(peripheral('sysctrl92', 0x44920000, 0x1000)) Reg("set5010001f", 0x44920004) -open('../src/include/phy/sysctrl92.h', 'w').write('\n'.join(GenHeader())) +#open('../src/include/phy/sysctrl92.h', 'w').write('\n'.join(GenHeader())) #print('\n'.join(GenHeader())) #print('\n'.join(GenSVD())) ############# Wifi IPC (EMB/Core) -Peripheral(peripheral('ipc', 0x44800000, 0x1000)) +peris['ipc'] = Peripheral(peripheral('ipc', 0x44800000, 0x1000)) for code, offset in getregs("../components/bl602/bl602_wifidrv/bl60x_wifi_driver/reg_ipc_app.h", pattern='brief'): RegFromComment(offset + 0x44800000, code) -open('../src/include/phy/ipc.h', 'w').write('\n'.join(GenHeader())) +#open('../src/include/phy/ipc.h', 'w').write('\n'.join(GenHeader())) #print('\n'.join(GenHeader())) -#print('\n'.join(GenSVD())) \ No newline at end of file +#print('\n'.join(GenSVD())) + +if __name__ == '__main__': + import sys + if len(sys.argv) == 1: + for p_name, p in peris.items(): + open(f"../src/include/phy/{p_name}.h", "w").write("\n".join(p.genHeader())) + else: + if len(sys.argv) >= 2: + addr = int(sys.argv[1], 16) + mask = 0 + if len(sys.argv) == 3: + mask = int(sys.argv[2], 16) + print(CAccess(peris, addr, mask)) \ No newline at end of file diff --git a/script/reglib.py b/script/reglib.py index 9e4d505..05a4fe7 100755 --- a/script/reglib.py +++ b/script/reglib.py @@ -296,6 +296,24 @@ def HasField(addr): return context.r.hasField(addr) print("You are not in any register") +def CAccess(peris, addr, mask): + for p_name, p in peris.items(): + if p.base <= addr and p.base + p.size >= addr: + r = p.findReg(addr) + if r: + if r.fields: + if mask == 0: + return f"{p_name.upper()}->{r.name}.value" + else: + f = r.hasField(mask) + if f: + return f"{p_name.upper()}->{r.name}.{f.name}" + else: + return f"({p_name.upper()}->{r.name}.value) & {hex(mask)}" + else: + return f"{p_name.upper()}->{r.name}" + + def RegFromComment(addr, comment:str): name = "" import re diff --git a/script/svd2c.py b/script/svd2c.py new file mode 100755 index 0000000..8eaa3d9 --- /dev/null +++ b/script/svd2c.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +import xml.etree.ElementTree as ET +from reglib import * +from typing import Mapping + +peris :Mapping[str, peripheral] = {} + +import pickle, os +if os.path.exists("./peris.cache"): + peris = pickle.load(open("./peris.cache", "rb")) +else: + tree = ET.parse('../components/bl602/bl602_std/bl602_std/Device/Bouffalo/BL602/Peripherals/soc602_reg.svd') + + root = tree.getroot() + + for p in root.iter('peripheral'): + p_name = p.find('name').text + baseAddress = int(p.find('baseAddress').text, 16) + addressSize = int(p.find('./addressBlock/size').text, 16) + + pp = Peripheral(peripheral(p_name, baseAddress, addressSize)) + for r in p.iter('register'): + r_name = r.find('name').text + r_offset = int(r.find('addressOffset').text, 16) + Reg(r_name, r_offset + baseAddress) + for f in p.iter('field'): + f_name = f.find('name').text + lsb = int(f.find('lsb').text) + msb = int(f.find('msb').text) + FieldBit(f_name, lsb, msb - lsb + 1) + peris[p_name] = pp + pickle.dump(peris, open("./peris.cache", "wb")) + +if __name__ == '__main__': + import sys + if len(sys.argv) == 1: + for p_name, p in peris.items(): + open(f"../src/include/soc/{p_name}.h", "w").write("\n".join(p.genHeader())) + else: + if len(sys.argv) >= 2: + addr = int(sys.argv[1], 16) + mask = 0 + if len(sys.argv) == 3: + mask = int(sys.argv[2], 16) + print(CAccess(peris, addr, mask)) \ No newline at end of file From ad428c3a8d8dfbf2fa4e1d0bb727815329a9ffc8 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 21 Jul 2021 19:17:19 -0500 Subject: [PATCH 013/148] no longer need to print the access code --- script/manualext.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/script/manualext.py b/script/manualext.py index d407d0d..c42cd9d 100755 --- a/script/manualext.py +++ b/script/manualext.py @@ -163,10 +163,11 @@ def scan_write(code): f = Field(name_f, mask) yield r.name, f.name, value -print("agc_config") +#print("agc_config") for rn, fn, val in scan_write(open('../blobs/agc_config.c').readlines()): - print(f"AGC->{rn}.{fn} = {hex(val)}") -print("ex") + pass + #print(f"AGC->{rn}.{fn} = {hex(val)}") +#print("ex") for rn, fn, val in scan_write([ "write_volatile_4(DAT_44c0c020,uVar4 & 0xfc00ffff | 0x140000);", "write_volatile_4(DAT_44c0b390,uVar1 & 0xfffffeff);", @@ -176,7 +177,8 @@ def scan_write(code): "write_volatile_4(DAT_44c0b110,uVar4 & 0xfffffffd);", "write_volatile_4(DAT_44c0b110,uVar4 & 0xfffffffe);", ]): - print(f"AGC->{rn}.{fn} = {hex(val)}") + pass + #print(f"AGC->{rn}.{fn} = {hex(val)}") #open('../src/include/phy/agc.h', 'w').write('\n'.join(GenHeader())) #print('\n'.join(GenHeader())) #print('\n'.join(GenSVD())) From d77652c374747eec71ccf4f2710210d14944aaf6 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 21 Jul 2021 05:11:03 -0500 Subject: [PATCH 014/148] add missing bit --- script/manualext.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/script/manualext.py b/script/manualext.py index c42cd9d..4c27eb2 100755 --- a/script/manualext.py +++ b/script/manualext.py @@ -25,7 +25,10 @@ Field('v30', 0xfffeffff) # some switch? DAT_44c00000>>30 Field('_v30', 0xffefffff) # some switch? DAT_44c00000>>30 FieldBit('reset', 0) # set 1 in phy_hw_set_channel for.. reset? +<<<<<<< HEAD Field('rxndpnstsmax', 0xffff8fff) +======= +>>>>>>> 42c4e98 (add missing bit) Reg('version', 0x44c00000) FieldBit('vht', 31-9) From f910c82f7e551019758fa62370d6fb0001084ecb Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 21 Jul 2021 05:11:19 -0500 Subject: [PATCH 015/148] add bit --- script/manualext.py | 3 --- src/include/phy/mdm.h | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/script/manualext.py b/script/manualext.py index 4c27eb2..c42cd9d 100755 --- a/script/manualext.py +++ b/script/manualext.py @@ -25,10 +25,7 @@ Field('v30', 0xfffeffff) # some switch? DAT_44c00000>>30 Field('_v30', 0xffefffff) # some switch? DAT_44c00000>>30 FieldBit('reset', 0) # set 1 in phy_hw_set_channel for.. reset? -<<<<<<< HEAD Field('rxndpnstsmax', 0xffff8fff) -======= ->>>>>>> 42c4e98 (add missing bit) Reg('version', 0x44c00000) FieldBit('vht', 31-9) diff --git a/src/include/phy/mdm.h b/src/include/phy/mdm.h index 8bdd17f..e536cf3 100644 --- a/src/include/phy/mdm.h +++ b/src/include/phy/mdm.h @@ -59,9 +59,9 @@ typedef union { uint32_t rxndpnstsmax : 3; // @ 14 -- 12 # 0xffff8fff uint32_t pad3 : 1; uint32_t v30 : 1; // @ 16 -- 16 # 0xfffeffff - uint32_t pad4 : 3; + uint32_t pad3 : 3; uint32_t _v30 : 1; // @ 20 -- 20 # 0xffefffff - uint32_t pad5 : 3; + uint32_t pad4 : 3; uint32_t rxcbwmax : 2; // @ 25 -- 24 # 0xfcffffff }; } rxchan; // @ 0x820 From cfbeae3658ef2b3923efffeb0d5c6aa97f63bd2f Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 21 Jul 2021 05:47:51 -0500 Subject: [PATCH 016/148] add missing rxndpnstsmax --- src/include/phy/mdm.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/phy/mdm.h b/src/include/phy/mdm.h index e536cf3..8bdd17f 100644 --- a/src/include/phy/mdm.h +++ b/src/include/phy/mdm.h @@ -59,9 +59,9 @@ typedef union { uint32_t rxndpnstsmax : 3; // @ 14 -- 12 # 0xffff8fff uint32_t pad3 : 1; uint32_t v30 : 1; // @ 16 -- 16 # 0xfffeffff - uint32_t pad3 : 3; - uint32_t _v30 : 1; // @ 20 -- 20 # 0xffefffff uint32_t pad4 : 3; + uint32_t _v30 : 1; // @ 20 -- 20 # 0xffefffff + uint32_t pad5 : 3; uint32_t rxcbwmax : 2; // @ 25 -- 24 # 0xfcffffff }; } rxchan; // @ 0x820 From 26793ff37539e6b16a3c9f4a3d6c0a7e78fa554a Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Thu, 22 Jul 2021 01:03:03 -0500 Subject: [PATCH 017/148] add bz_phyfunc --- script/manualext.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/script/manualext.py b/script/manualext.py index c42cd9d..94e58ba 100755 --- a/script/manualext.py +++ b/script/manualext.py @@ -331,6 +331,11 @@ def getregs(fname, pattern='name'): #print('\n'.join(GenHeader())) #print('\n'.join(GenSVD())) + +peris['bz_phy'] = Peripheral(peripheral('bz_phy', 0x40002000, 0x1000)) +scan_write(open('../blobs/bz_phy.c').readlines()) + + if __name__ == '__main__': import sys if len(sys.argv) == 1: From 377b3c2b8e05203fb4281351d1cf1692c0f80cb5 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Thu, 22 Jul 2021 01:03:18 -0500 Subject: [PATCH 018/148] add bz_phy.h --- src/include/phy/bz_phy.h | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/include/phy/bz_phy.h diff --git a/src/include/phy/bz_phy.h b/src/include/phy/bz_phy.h new file mode 100644 index 0000000..354d4d5 --- /dev/null +++ b/src/include/phy/bz_phy.h @@ -0,0 +1,8 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + }; +} bz_phy_regs; +#define BZ_PHY_BASE 0x40002000 +#define BZ_PHY ((bz_phy_regs* volatile)(BZ_PHY_BASE)) \ No newline at end of file From 3ce657a2d55ebd88e7f736f068ee104ce9992377 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Thu, 22 Jul 2021 01:10:49 -0500 Subject: [PATCH 019/148] add support for 0x --- script/manualext.py | 9 ++++++--- src/include/phy/bz_phy.h | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/script/manualext.py b/script/manualext.py index 94e58ba..d2c8244 100755 --- a/script/manualext.py +++ b/script/manualext.py @@ -134,9 +134,12 @@ gid = 0 -def scan_write(code): +def scan_write(code, dat="dat"): global gid - write_pattern = r'write_volatile_4\(DAT_([0-9a-f]+),uVar\d( & 0x([0-9a-f]+))*( \| 0x([0-9a-f]+))*\);' + if dat == 'dat': + write_pattern = r'write_volatile_4\(DAT_([0-9a-f]+),uVar\d( & 0x([0-9a-f]+))*( \| 0x([0-9a-f]+))*\);' + else: + write_pattern = r'write_volatile_4\(0x([0-9a-f]+),uVar\d( & 0x([0-9a-f]+))*( \| 0x([0-9a-f]+))*\);' for l in code: import re g = re.search(write_pattern, l) @@ -333,7 +336,7 @@ def getregs(fname, pattern='name'): peris['bz_phy'] = Peripheral(peripheral('bz_phy', 0x40002000, 0x1000)) -scan_write(open('../blobs/bz_phy.c').readlines()) +scan_write(open('../blobs/bz_phy.c').readlines(), '0x') if __name__ == '__main__': diff --git a/src/include/phy/bz_phy.h b/src/include/phy/bz_phy.h index 354d4d5..f81f5cd 100644 --- a/src/include/phy/bz_phy.h +++ b/src/include/phy/bz_phy.h @@ -2,6 +2,40 @@ typedef union { uint32_t regs[0x400]; uint8_t pad[0x1000]; struct { + uint8_t pad0[0x808]; + union { + uint32_t value; + struct { + uint32_t pad0 : 23; + uint32_t set_0x1_67 : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t set_0x8_68 : 8; // @ 31 -- 24 # 0xffffff + }; + } r0x2808; // @ 0x808 + union { + uint32_t value; + struct { + uint32_t set_0x0_71 : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pad0 : 15; + uint32_t set_0x1_69 : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t set_0x4_70 : 8; // @ 31 -- 24 # 0xffffff + }; + } r0x280c; // @ 0x80c + union { + uint32_t value; + struct { + uint32_t set_0x0_76 : 1; // @ 0 -- 0 # 0xfffffffe + }; + } r0x2810; // @ 0x810 + uint8_t pad1[0x40]; + union { + uint32_t value; + struct { + uint32_t set_0x1e_75 : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t set_0x20_72 : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t set_0xa_74 : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t set_0x1e_73 : 8; // @ 31 -- 24 # 0xffffff + }; + } r0x2854; // @ 0x854 }; } bz_phy_regs; #define BZ_PHY_BASE 0x40002000 From 55be85b90a93c73f47c3feb92612e42ae4fc2977 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Thu, 22 Jul 2021 01:24:19 -0500 Subject: [PATCH 020/148] foreach in scan --- script/manualext.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/script/manualext.py b/script/manualext.py index d2c8244..6821868 100755 --- a/script/manualext.py +++ b/script/manualext.py @@ -336,7 +336,9 @@ def getregs(fname, pattern='name'): peris['bz_phy'] = Peripheral(peripheral('bz_phy', 0x40002000, 0x1000)) -scan_write(open('../blobs/bz_phy.c').readlines(), '0x') +for rn, fn, val in scan_write(open('../blobs/bz_phy.c').readlines(), '0x'): + pass + #print(f"BZ_PHY->{rn}.{fn} = {hex(val)}") if __name__ == '__main__': From 7261e1c67412b22daa5d74b29de9c95259674e21 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Thu, 22 Jul 2021 01:10:49 -0500 Subject: [PATCH 021/148] add support for 0x --- src/bl602_wifi/phy_bl602.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/bl602_wifi/phy_bl602.c b/src/bl602_wifi/phy_bl602.c index d7401b1..7858ac0 100644 --- a/src/bl602_wifi/phy_bl602.c +++ b/src/bl602_wifi/phy_bl602.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "phy_bl602.h" #include "phy_trpc.h" @@ -123,7 +124,16 @@ void agc_config(void) { } void bz_phy_reset(void) { - // UNUSED Function + BZ_PHY->r0x2808.set_0x1_67 = 0x1; + BZ_PHY->r0x2808.set_0x8_68 = 0x8; + BZ_PHY->r0x280c.set_0x1_69 = 0x1; + BZ_PHY->r0x280c.set_0x4_70 = 0x4; + BZ_PHY->r0x280c.set_0x0_71 = 0x0; + BZ_PHY->r0x2854.set_0x20_72 = 0x20; + BZ_PHY->r0x2854.set_0x1e_73 = 0x1e; + BZ_PHY->r0x2854.set_0xa_74 = 0xa; + BZ_PHY->r0x2854.set_0x1e_75 = 0x1e; + BZ_PHY->r0x2810.set_0x0_76 = 0x0; return ; } From ec7126964ce44584c6618aaf74507ef2f20d1d45 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Thu, 22 Jul 2021 01:28:13 -0500 Subject: [PATCH 022/148] fix bz_phy.c --- blobs/bz_phy.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 blobs/bz_phy.c diff --git a/blobs/bz_phy.c b/blobs/bz_phy.c new file mode 100644 index 0000000..97c9944 --- /dev/null +++ b/blobs/bz_phy.c @@ -0,0 +1,31 @@ +void bz_phy_reset(void) + +{ + uint uVar1; + + uVar1 = read_volatile_4(0x40002808); + write_volatile_4(0x40002808,uVar1 & 0xff7fffff | 0x800000); + uVar1 = read_volatile_4(0x40002808); + write_volatile_4(0x40002808,uVar1 & 0xffffff | 0x8000000); + uVar1 = read_volatile_4(0x4000280c); + write_volatile_4(0x4000280c,uVar1 & 0xff7fffff | 0x800000); + uVar1 = read_volatile_4(0x4000280c); + write_volatile_4(0x4000280c,uVar1 & 0xffffff | 0x4000000); + uVar1 = read_volatile_4(0x4000280c); + write_volatile_4(0x4000280c,uVar1 & 0xffffff00); + uVar1 = read_volatile_4(0x40002854); + write_volatile_4(0x40002854,uVar1 & 0xffff00ff | 0x2000); + uVar1 = read_volatile_4(0x40002854); + write_volatile_4(0x40002854,uVar1 & 0xffffff | 0x1e000000); + uVar1 = read_volatile_4(0x40002854); + write_volatile_4(0x40002854,uVar1 & 0xff00ffff | 0xa0000); + uVar1 = read_volatile_4(0x40002854); + write_volatile_4(0x40002854,uVar1 & 0xffffff00 | 0x1e); + uVar1 = read_volatile_4(0x40002810); + write_volatile_4(0x40002810,uVar1 & 0xfffffffe); + uVar1 = read_volatile_4(0x40002810); + write_volatile_4(0x40002810,uVar1 | 0x2); + uVar1 = read_volatile_4(0x40002cac); + write_volatile_4(0x40002cac,uVar1 & 0xffffffe0 | 0x4); + return; +} \ No newline at end of file From f32ad885d7c3e257f5c6f82f6143515708d4f838 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Thu, 22 Jul 2021 01:29:29 -0500 Subject: [PATCH 023/148] add bz_phy_reset --- src/bl602_wifi/phy_bl602.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bl602_wifi/phy_bl602.c b/src/bl602_wifi/phy_bl602.c index 7858ac0..7931908 100644 --- a/src/bl602_wifi/phy_bl602.c +++ b/src/bl602_wifi/phy_bl602.c @@ -134,6 +134,8 @@ void bz_phy_reset(void) { BZ_PHY->r0x2854.set_0xa_74 = 0xa; BZ_PHY->r0x2854.set_0x1e_75 = 0x1e; BZ_PHY->r0x2810.set_0x0_76 = 0x0; + BZ_PHY->r0x2810.set_0x1_77 = 0x1; + BZ_PHY->r0x2cac.set_0x4_78 = 0x4; return ; } From c98ef5a3e620cf43a4ca2bd5782409901c4049cb Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Thu, 22 Jul 2021 01:30:12 -0500 Subject: [PATCH 024/148] new header --- src/include/phy/bz_phy.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/include/phy/bz_phy.h b/src/include/phy/bz_phy.h index f81f5cd..a2ba2df 100644 --- a/src/include/phy/bz_phy.h +++ b/src/include/phy/bz_phy.h @@ -24,6 +24,7 @@ typedef union { uint32_t value; struct { uint32_t set_0x0_76 : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t set_0x1_77 : 1; // @ 1 -- 1 # 0xfffffffd }; } r0x2810; // @ 0x810 uint8_t pad1[0x40]; @@ -36,6 +37,13 @@ typedef union { uint32_t set_0x1e_73 : 8; // @ 31 -- 24 # 0xffffff }; } r0x2854; // @ 0x854 + uint8_t pad2[0x454]; + union { + uint32_t value; + struct { + uint32_t set_0x4_78 : 5; // @ 4 -- 0 # 0xffffffe0 + }; + } r0x2cac; // @ 0xcac }; } bz_phy_regs; #define BZ_PHY_BASE 0x40002000 From fc7f9f889aea977446695f5d28c255cc33853de6 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 21 Jul 2021 19:14:14 -0500 Subject: [PATCH 025/148] support parse bl svd file and find reg with addr and mask --- script/manualext.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/script/manualext.py b/script/manualext.py index 6821868..dc98b5a 100755 --- a/script/manualext.py +++ b/script/manualext.py @@ -334,6 +334,7 @@ def getregs(fname, pattern='name'): #print('\n'.join(GenHeader())) #print('\n'.join(GenSVD())) +<<<<<<< HEAD peris['bz_phy'] = Peripheral(peripheral('bz_phy', 0x40002000, 0x1000)) for rn, fn, val in scan_write(open('../blobs/bz_phy.c').readlines(), '0x'): @@ -341,6 +342,8 @@ def getregs(fname, pattern='name'): #print(f"BZ_PHY->{rn}.{fn} = {hex(val)}") +======= +>>>>>>> d18fd82 (support parse bl svd file and find reg with addr and mask) if __name__ == '__main__': import sys if len(sys.argv) == 1: From 58095db6601fca26c6825cb58555352bdeb91870 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Thu, 22 Jul 2021 01:03:03 -0500 Subject: [PATCH 026/148] add bz_phyfunc --- script/manualext.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/script/manualext.py b/script/manualext.py index dc98b5a..64fee3f 100755 --- a/script/manualext.py +++ b/script/manualext.py @@ -334,16 +334,12 @@ def getregs(fname, pattern='name'): #print('\n'.join(GenHeader())) #print('\n'.join(GenSVD())) -<<<<<<< HEAD peris['bz_phy'] = Peripheral(peripheral('bz_phy', 0x40002000, 0x1000)) for rn, fn, val in scan_write(open('../blobs/bz_phy.c').readlines(), '0x'): pass #print(f"BZ_PHY->{rn}.{fn} = {hex(val)}") - -======= ->>>>>>> d18fd82 (support parse bl svd file and find reg with addr and mask) if __name__ == '__main__': import sys if len(sys.argv) == 1: From c8111a78dc1d70a7ff71c3b09fee75067ed1ffc0 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Fri, 23 Jul 2021 03:53:18 -0500 Subject: [PATCH 027/148] more stable name --- script/manualext.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/script/manualext.py b/script/manualext.py index 64fee3f..a987640 100755 --- a/script/manualext.py +++ b/script/manualext.py @@ -147,10 +147,12 @@ def scan_write(code, dat="dat"): continue value = 0 addr = int(g.group(1), 16) + lsb = 0 if g.group(3) == None: # mask value = int(g.group(5), 16) mask = (~value) & 0xffffffff - value = value >> ((value & (-value)).bit_length() - 1) + lsb = ((value & (-value)).bit_length() - 1) + value = value >> lsb else: mask = int(g.group(3), 16) if g.group(5): # value @@ -159,7 +161,9 @@ def scan_write(code, dat="dat"): lsb = lsb.bit_length() - 1 value = int(g.group(5), 16) value = value >> lsb - name_f = f'set_{hex(value)}_{gid}' + else: + lsb = 0 + name_f = f'set_{hex(value)}_{lsb}' name_r = f'r{hex(addr&0xffff)}' gid = gid + 1 r = Reg(name_r, addr) From 5a877e604409be34a3a7b18c32e304f827616635 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sat, 24 Jul 2021 02:21:39 -0500 Subject: [PATCH 028/148] add extra information from DWARF --- script/manualext.py | 145 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 127 insertions(+), 18 deletions(-) diff --git a/script/manualext.py b/script/manualext.py index a987640..0912ee3 100755 --- a/script/manualext.py +++ b/script/manualext.py @@ -92,9 +92,9 @@ Field('smoothsnrthrmid', 0xffffff00) Reg('rxctrl1', 0x44c0083c) # reset to 0x4920492 -Reg('r874', 0x44c00874) +Reg('r0x874', 0x44c00874) Field('resetto1', 0xf7ffffff) -Field('set1beforewriteagcmem', 0xdfffffff) +Field('mdm_agcmemclkforce', 0xdfffffff) #print('\n'.join(GenSVD())) @@ -105,6 +105,16 @@ Reg('r000', 0x44c0b000) FieldBit('iqcomp', 31-10) +### guess +Reg('RWNXAGCRAMP', 0x44c0b36c) +FieldBit('RAMPDNNDLINDEX', 24, 3) # 0x05 +FieldBit('RAMPDNGAPQDB', 16, 8) # 0x20 +FieldBit('RAMPUPNDLINDEX', 8, 3) # 0x7 +FieldBit('RAMPUPGAPQDB', 0, 8) # 0x20 + +### + + Reg('RWNXAGCCNTL', 0x44c0b390) Field('set1', 0xfffffffc) Field('agcfsmreset', 0xffffefff) # set 1 before agc mem, maybe @@ -137,9 +147,9 @@ def scan_write(code, dat="dat"): global gid if dat == 'dat': - write_pattern = r'write_volatile_4\(DAT_([0-9a-f]+),uVar\d( & 0x([0-9a-f]+))*( \| 0x([0-9a-f]+))*\);' + write_pattern = r'write_volatile_4\(DAT_([0-9a-f]+),uVar\d( & 0x([0-9a-f]+))*( \| ([0-9a-z]+))*\);' else: - write_pattern = r'write_volatile_4\(0x([0-9a-f]+),uVar\d( & 0x([0-9a-f]+))*( \| 0x([0-9a-f]+))*\);' + write_pattern = r'write_volatile_4\(0x([0-9a-f]+),uVar\d( & 0x([0-9a-f]+))*( \| ([0-9a-z]+))*\);' for l in code: import re g = re.search(write_pattern, l) @@ -167,15 +177,94 @@ def scan_write(code, dat="dat"): name_r = f'r{hex(addr&0xffff)}' gid = gid + 1 r = Reg(name_r, addr) - f = Field(name_f, mask) - yield r.name, f.name, value - -#print("agc_config") -for rn, fn, val in scan_write(open('../blobs/agc_config.c').readlines()): - pass - #print(f"AGC->{rn}.{fn} = {hex(val)}") -#print("ex") -for rn, fn, val in scan_write([ + yield r, Field(name_f, mask) + + +agc_attr = [ + (0x44c0b390, "riu_htstfgainen"), + (0x44c0b390, "riu_rifsdeten"), + (0x44c0b3a4, "riu_fe20gain"), + (0x44c0b3a4, "riu_fe40gain"), + (0x44c0b394, "riu_vpeakadcqdbv"), + (0x44c0b398, "riu_adcpowmindbm"), + (0x44c0b3c4, "riu_adcpowsupthrdbm"), + (0x44c0b364, "riu_satdelay50ns"), + (0x44c0b364, "riu_sathighthrdbv"), + (0x44c0b364, "riu_satlowthrdbv"), + (0x44c0b364, "riu_satthrdbv"), + (0x44c0b368, "riu_crossdnthrqdbm"), + (0x44c0b368, "riu_crossupthrqdbm"), + (0x44c0b36c, "riu_rampupgapqdb"), + (0x44c0b36c, "riu_rampupndlindex"), + (0x44c0b36c, "riu_rampdngapqdb"), + (0x44c0b36c, "riu_rampdnndlindex"), + (0x44c0b370, "riu_adcpowdisthrdbv"), + (0x44c0b3c0, "riu_idinbdpowgapdnqdbm"), + (0x44c0b380, "riu_evt0op3"), + (0x44c0b380, "riu_evt0op2"), + (0x44c0b380, "riu_evt0op1"), + (0x44c0b380, "riu_evt0pathcomb"), + (0x44c0b380, "riu_evt0opcomb"), + (0x44c0b384, "riu_evt1op1"), + (0x44c0b384, "riu_evt1op2"), + (0x44c0b384, "riu_evt1op3"), + (0x44c0b384, "riu_evt1pathcomb"), + (0x44c0b384, "riu_evt1opcomb"), + (0x44c0b388, "riu_evt2op1"), + (0x44c0b388, "riu_evt2op2"), + (0x44c0b388, "riu_evt2op3"), + (0x44c0b388, "riu_evt2pathcomb"), + (0x44c0b388, "riu_evt2opcomb"), + (0x44c0b38c, "riu_evt3op1"), + (0x44c0b38c, "riu_evt3op2"), + (0x44c0b38c, "riu_evt3op3"), + (0x44c0b38c, "riu_evt3opcomb"), + (0x44c0c830, "rc2_evt4op1"), + (0x44c0c830, "rc2_evt4op2"), + (0x44c0c830, "rc2_evt4op3"), + (0x44c0c830, "rc2_evt4opcomb"), + (0x44c0c814, "rc2_pkdet_mode"), + (0x44c0c814, "rc2_pkdet_cnt_thr"), + (0x44c0c814, "rc2_pkdet_cnt_thr"), + (0x44c0c040, "rc2_rx0_vga_idx_max"), + (0x44c0c040, "rc2_rx0_vga_idx_min"), + (0x44c0c044, "rc2_rx0_lna_idx_max"), + (0x44c0c044, "rc2_rx0_lna_idx_min"), + (0x44c0b3a0, "riu_inbdpowmindbm"), + (0x44c0b3c0, "riu_inbdpowsupthrdbm"), + (0x44c0b3c0, "riu_inbdpowinfthrdbm"), + (0x44c0c82c, "rc2_inbdpow_adj_thr_dbm"), + (0x44c0c82c, "rc2_inbdpowsupthr_adj_en"), + (0x44c0c82c, "rc2_inbdpowinfthr_adj_en"), + (0x44c0c838, "rc2_reflevofdmthd_en"), + (0x44c0c838, "rc2_reflevofdmthd"), + (0x44c0c83c, "rc2_reflevdsssthd_en"), + (0x44c0c83c, "rc2_reflevdsssthd"), + (0x44c0c840, "rc2_reflevdssscontthd_en"), + (0x44c0c840, "rc2_reflevdssscontthd"), + (0x44c0c82c, "rc2_inbdpowfastvalid_cnt"), +] + +i = 0 +for r, f in scan_write(open('../blobs/agc_config.c').readlines()): + if r.offset == agc_attr[i][0] - 0x44c0b000: + f.name = agc_attr[i][1] + else: + print(f"mismatched {i} {agc_attr[i][1]} {hex(r.offset + 0x44c0b000)} {hex(agc_attr[i][0])}") + i = i + 1 + +extra_regs = [ + "rc_paoff_delay", + "riu_agcfsmreset", + "riu_txshift4044", + "riu_rxiqphaseesten", + "riu_rxiqgainesten", + "riu_rxiqphasecompen", + "riu_rxiqgaincompen" +] + +i = 0 +for _, f in scan_write([ "write_volatile_4(DAT_44c0c020,uVar4 & 0xfc00ffff | 0x140000);", "write_volatile_4(DAT_44c0b390,uVar1 & 0xfffffeff);", "write_volatile_4(DAT_44c0b500,uVar4 & 0xffffcfff | 0x2000);", @@ -184,8 +273,8 @@ def scan_write(code, dat="dat"): "write_volatile_4(DAT_44c0b110,uVar4 & 0xfffffffd);", "write_volatile_4(DAT_44c0b110,uVar4 & 0xfffffffe);", ]): - pass - #print(f"AGC->{rn}.{fn} = {hex(val)}") + f.name = agc_attr[i][1] + i = i + 1 #open('../src/include/phy/agc.h', 'w').write('\n'.join(GenHeader())) #print('\n'.join(GenHeader())) #print('\n'.join(GenSVD())) @@ -340,9 +429,29 @@ def getregs(fname, pattern='name'): peris['bz_phy'] = Peripheral(peripheral('bz_phy', 0x40002000, 0x1000)) -for rn, fn, val in scan_write(open('../blobs/bz_phy.c').readlines(), '0x'): - pass - #print(f"BZ_PHY->{rn}.{fn} = {hex(val)}") + +extra_bz_phy = [ +(0x40002808,"bz_phy_tx_rampup_fm_on"), +(0x40002808,"bz_phy_tx_rampup_time_us"), +(0x4000280c,"bz_phy_tx_rampdn_fm_on"), +(0x4000280c,"bz_phy_tx_rampdn_time_us"), +(0x4000280c,"bz_phy_tx_rampdn_pad0_time_us"), +(0x40002854,"bz_phy_rx_proc_time_mlsd_us"), +(0x40002854,"bz_phy_rx_proc_time_direct_us"), +(0x40002854,"bz_phy_rx_proc_time_eq_us"), +(0x40002854,"bz_phy_rx_proc_time_viterbi_us"), +(0x40002810,"bz_phy_rx_dfe_notch_en"), +(0x40002810,"bz_phy_rx_dfe_toc_en"), +(0x40002cac,"bz_agc_rbb_ind_min"), +] + +i = 0 +for r, f in scan_write(open('../blobs/bz_phy.c').readlines(), '0x'): + if r.offset == extra_bz_phy[i][0] - 0x40002000: + f.name = extra_bz_phy[i][1] + else: + print(f"mismatched {i} {extra_bz_phy[i][1]} {hex(r.offset + 0x40002000)} {hex(extra_bz_phy[i][0])}") + i = i + 1 if __name__ == '__main__': import sys From 95cf6ec12e6426127f2bbbeed3b41916907e153a Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sat, 24 Jul 2021 02:22:45 -0500 Subject: [PATCH 029/148] add extra names --- src/include/phy/agc.h | 137 ++++++++++++++++++++------------------- src/include/phy/bz_phy.h | 24 +++---- src/include/phy/mdm.h | 4 +- 3 files changed, 83 insertions(+), 82 deletions(-) diff --git a/src/include/phy/agc.h b/src/include/phy/agc.h index e3c4e4e..15fc4a8 100644 --- a/src/include/phy/agc.h +++ b/src/include/phy/agc.h @@ -14,10 +14,10 @@ typedef union { union { uint32_t value; struct { - uint32_t set_0x0_66 : 1; // @ 0 -- 0 # 0xfffffffe - uint32_t set_0x0_65 : 1; // @ 1 -- 1 # 0xfffffffd - uint32_t set_0x0_64 : 1; // @ 2 -- 2 # 0xfffffffb - uint32_t set_0x0_63 : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t riu_adcpowsupthrdbm : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t riu_adcpowmindbm : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t riu_vpeakadcqdbv : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t riu_fe40gain : 1; // @ 3 -- 3 # 0xfffffff7 }; } r0xb110; // @ 0x110 uint8_t pad1[0x4]; @@ -30,38 +30,38 @@ typedef union { union { uint32_t value; struct { - uint32_t set_0x39_10 : 6; // @ 5 -- 0 # 0xffffffc0 + uint32_t riu_satthrdbv : 6; // @ 5 -- 0 # 0xffffffc0 uint32_t pad0 : 2; - uint32_t set_0x38_9 : 6; // @ 13 -- 8 # 0xffffc0ff + uint32_t riu_satlowthrdbv : 6; // @ 13 -- 8 # 0xffffc0ff uint32_t pad1 : 2; - uint32_t set_0x3c_8 : 6; // @ 21 -- 16 # 0xffc0ffff + uint32_t riu_sathighthrdbv : 6; // @ 21 -- 16 # 0xffc0ffff uint32_t pad2 : 2; - uint32_t set_0x8_7 : 5; // @ 28 -- 24 # 0xe0ffffff + uint32_t riu_satdelay50ns : 5; // @ 28 -- 24 # 0xe0ffffff }; } r0xb364; // @ 0x364 union { uint32_t value; struct { - uint32_t set_0x70_12 : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t riu_crossupthrqdbm : 10; // @ 9 -- 0 # 0xfffffc00 uint32_t pad0 : 2; - uint32_t set_0x70_11 : 10; // @ 21 -- 12 # 0xffc00fff + uint32_t riu_crossdnthrqdbm : 10; // @ 21 -- 12 # 0xffc00fff }; } r0xb368; // @ 0x368 union { uint32_t value; struct { - uint32_t set_0x12_13 : 8; // @ 7 -- 0 # 0xffffff00 - uint32_t set_0x5_14 : 3; // @ 10 -- 8 # 0xfffff8ff + uint32_t riu_rampupgapqdb : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t riu_rampupndlindex : 3; // @ 10 -- 8 # 0xfffff8ff uint32_t pad0 : 5; - uint32_t set_0x28_15 : 8; // @ 23 -- 16 # 0xff00ffff - uint32_t set_0x7_16 : 3; // @ 26 -- 24 # 0xf8ffffff + uint32_t riu_rampdngapqdb : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t riu_rampdnndlindex : 3; // @ 26 -- 24 # 0xf8ffffff }; - } r0xb36c; // @ 0x36c + } RWNXAGCRAMP; // @ 0x36c union { uint32_t value; struct { uint32_t pad0 : 16; - uint32_t set_0x58_17 : 7; // @ 22 -- 16 # 0xff80ffff + uint32_t riu_adcpowdisthrdbv : 7; // @ 22 -- 16 # 0xff80ffff }; } r0xb370; // @ 0x370 uint8_t pad4[0xc]; @@ -69,44 +69,44 @@ typedef union { uint32_t value; struct { uint32_t pad0 : 10; - uint32_t set_0x1_23 : 3; // @ 12 -- 10 # 0xffffe3ff - uint32_t set_0x0_22 : 1; // @ 13 -- 13 # 0xffffdfff - uint32_t set_0x3e_19 : 6; // @ 19 -- 14 # 0xfff03fff - uint32_t set_0x37_20 : 6; // @ 25 -- 20 # 0xfc0fffff - uint32_t set_0x1_21 : 6; // @ 31 -- 26 # 0x3ffffff + uint32_t riu_evt0opcomb : 3; // @ 12 -- 10 # 0xffffe3ff + uint32_t riu_evt0pathcomb : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t riu_evt0op3 : 6; // @ 19 -- 14 # 0xfff03fff + uint32_t riu_evt0op2 : 6; // @ 25 -- 20 # 0xfc0fffff + uint32_t riu_evt0op1 : 6; // @ 31 -- 26 # 0x3ffffff }; } r0xb380; // @ 0x380 union { uint32_t value; struct { uint32_t pad0 : 10; - uint32_t set_0x2_28 : 3; // @ 12 -- 10 # 0xffffe3ff - uint32_t set_0x0_27 : 1; // @ 13 -- 13 # 0xffffdfff - uint32_t set_0x14_26 : 6; // @ 19 -- 14 # 0xfff03fff - uint32_t set_0x37_25 : 6; // @ 25 -- 20 # 0xfc0fffff - uint32_t set_0x39_24 : 6; // @ 31 -- 26 # 0x3ffffff + uint32_t riu_evt1opcomb : 3; // @ 12 -- 10 # 0xffffe3ff + uint32_t riu_evt1pathcomb : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t riu_evt1op3 : 6; // @ 19 -- 14 # 0xfff03fff + uint32_t riu_evt1op2 : 6; // @ 25 -- 20 # 0xfc0fffff + uint32_t riu_evt1op1 : 6; // @ 31 -- 26 # 0x3ffffff }; } r0xb384; // @ 0x384 union { uint32_t value; struct { uint32_t pad0 : 10; - uint32_t set_0x5_33 : 3; // @ 12 -- 10 # 0xffffe3ff - uint32_t set_0x0_32 : 1; // @ 13 -- 13 # 0xffffdfff - uint32_t set_0x2a_31 : 6; // @ 19 -- 14 # 0xfff03fff - uint32_t set_0x17_30 : 6; // @ 25 -- 20 # 0xfc0fffff - uint32_t set_0xf_29 : 6; // @ 31 -- 26 # 0x3ffffff + uint32_t riu_evt2opcomb : 3; // @ 12 -- 10 # 0xffffe3ff + uint32_t riu_evt2pathcomb : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t riu_evt2op3 : 6; // @ 19 -- 14 # 0xfff03fff + uint32_t riu_evt2op2 : 6; // @ 25 -- 20 # 0xfc0fffff + uint32_t riu_evt2op1 : 6; // @ 31 -- 26 # 0x3ffffff }; } r0xb388; // @ 0x388 union { uint32_t value; struct { uint32_t pad0 : 10; - uint32_t set_0x2_37 : 3; // @ 12 -- 10 # 0xffffe3ff + uint32_t riu_evt3opcomb : 3; // @ 12 -- 10 # 0xffffe3ff uint32_t pad1 : 1; - uint32_t set_0xe_36 : 6; // @ 19 -- 14 # 0xfff03fff - uint32_t set_0x0_35 : 6; // @ 25 -- 20 # 0xfc0fffff - uint32_t set_0x19_34 : 6; // @ 31 -- 26 # 0x3ffffff + uint32_t riu_evt3op3 : 6; // @ 19 -- 14 # 0xfff03fff + uint32_t riu_evt3op2 : 6; // @ 25 -- 20 # 0xfc0fffff + uint32_t riu_evt3op1 : 6; // @ 31 -- 26 # 0x3ffffff }; } r0xb38c; // @ 0x38c union { @@ -114,41 +114,41 @@ typedef union { struct { uint32_t set1 : 2; // @ 1 -- 0 # 0xfffffffc uint32_t pad0 : 6; - uint32_t set_0x0_61 : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t riu_rifsdeten : 1; // @ 8 -- 8 # 0xfffffeff uint32_t pad1 : 1; - uint32_t set_0x0_1 : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t riu_rifsdeten : 1; // @ 10 -- 10 # 0xfffffbff uint32_t pad2 : 1; uint32_t agcfsmreset : 1; // @ 12 -- 12 # 0xffffefff uint32_t pad3 : 3; - uint32_t set_0x0_0 : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t riu_htstfgainen : 1; // @ 16 -- 16 # 0xfffeffff }; } RWNXAGCCNTL; // @ 0x390 union { uint32_t value; struct { uint32_t pad0 : 16; - uint32_t set_0xf8_4 : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t riu_vpeakadcqdbv : 8; // @ 23 -- 16 # 0xff00ffff }; } r0xb394; // @ 0x394 union { uint32_t value; struct { uint32_t pad0 : 8; - uint32_t set_0x9e_5 : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t riu_adcpowmindbm : 8; // @ 15 -- 8 # 0xffff00ff }; } r0xb398; // @ 0x398 uint8_t pad5[0x4]; union { uint32_t value; struct { - uint32_t set_0x9e_47 : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t riu_inbdpowmindbm : 8; // @ 7 -- 0 # 0xffffff00 }; } r0xb3a0; // @ 0x3a0 union { uint32_t value; struct { - uint32_t set_0x0_2 : 8; // @ 7 -- 0 # 0xffffff00 - uint32_t set_0x0_3 : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t riu_fe20gain : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t riu_fe40gain : 8; // @ 15 -- 8 # 0xffff00ff }; } r0xb3a4; // @ 0x3a4 uint8_t pad6[0x14]; @@ -156,16 +156,16 @@ typedef union { union { uint32_t value; struct { - uint32_t set_0xa4_48 : 8; // @ 7 -- 0 # 0xffffff00 - uint32_t set_0xa3_49 : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t riu_inbdpowsupthrdbm : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t riu_inbdpowinfthrdbm : 8; // @ 15 -- 8 # 0xffff00ff uint32_t pad0 : 8; - uint32_t set_0x18_18 : 8; // @ 31 -- 24 # 0xffffff + uint32_t riu_idinbdpowgapdnqdbm : 8; // @ 31 -- 24 # 0xffffff }; } r0xb3c0; // @ 0x3c0 union { uint32_t value; struct { - uint32_t set_0xce_6 : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t riu_adcpowsupthrdbm : 8; // @ 7 -- 0 # 0xffffff00 }; } r0xb3c4; // @ 0x3c4 uint8_t pad7[0x4c]; @@ -190,7 +190,7 @@ typedef union { uint32_t value; struct { uint32_t pad0 : 12; - uint32_t set_0x2_62 : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t riu_fe20gain : 2; // @ 13 -- 12 # 0xffffcfff }; } r0xb500; // @ 0x500 uint8_t pad10[0xb1c]; @@ -198,7 +198,7 @@ typedef union { uint32_t value; struct { uint32_t pad0 : 16; - uint32_t set_0x14_60 : 10; // @ 25 -- 16 # 0xfc00ffff + uint32_t riu_htstfgainen : 10; // @ 25 -- 16 # 0xfc00ffff }; } r0xc020; // @ 0x1020 uint8_t pad11[0x1c]; @@ -206,15 +206,15 @@ typedef union { uint32_t value; struct { uint32_t pad0 : 15; - uint32_t set_0x3_44 : 5; // @ 19 -- 15 # 0xfff07fff - uint32_t set_0xc_43 : 5; // @ 24 -- 20 # 0xfe0fffff + uint32_t rc2_rx0_vga_idx_min : 5; // @ 19 -- 15 # 0xfff07fff + uint32_t rc2_rx0_vga_idx_max : 5; // @ 24 -- 20 # 0xfe0fffff }; } r0xc040; // @ 0x1040 union { uint32_t value; struct { - uint32_t set_0x0_46 : 8; // @ 7 -- 0 # 0xffffff00 - uint32_t set_0x8_45 : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t rc2_rx0_lna_idx_min : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t rc2_rx0_lna_idx_max : 8; // @ 15 -- 8 # 0xffff00ff }; } r0xc044; // @ 0x1044 uint8_t pad12[0x38]; @@ -230,55 +230,56 @@ typedef union { union { uint32_t value; struct { - uint32_t set_0x0_42 : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t rc2_pkdet_mode : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t rc2_pkdet_cnt_thr : 4; // @ 5 -- 2 # 0xffffffc3 }; } r0xc814; // @ 0x1814 uint8_t pad15[0x14]; union { uint32_t value; struct { - uint32_t set_0xb5_50 : 8; // @ 7 -- 0 # 0xffffff00 - uint32_t set_0x1_51 : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t rc2_inbdpow_adj_thr_dbm : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t rc2_inbdpowsupthr_adj_en : 1; // @ 8 -- 8 # 0xfffffeff uint32_t pad0 : 2; - uint32_t set_0x1_52 : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t rc2_inbdpowinfthr_adj_en : 1; // @ 11 -- 11 # 0xfffff7ff uint32_t pad1 : 3; - uint32_t set_0x40_59 : 9; // @ 23 -- 15 # 0xff007fff + uint32_t rc2_inbdpowfastvalid_cnt : 9; // @ 23 -- 15 # 0xff007fff }; } r0xc82c; // @ 0x182c union { uint32_t value; struct { uint32_t pad0 : 10; - uint32_t set_0x5_41 : 3; // @ 12 -- 10 # 0xffffe3ff + uint32_t rc2_evt4opcomb : 3; // @ 12 -- 10 # 0xffffe3ff uint32_t pad1 : 1; - uint32_t set_0x36_40 : 6; // @ 19 -- 14 # 0xfff03fff - uint32_t set_0x1_39 : 6; // @ 25 -- 20 # 0xfc0fffff - uint32_t set_0x3f_38 : 6; // @ 31 -- 26 # 0x3ffffff + uint32_t rc2_evt4op3 : 6; // @ 19 -- 14 # 0xfff03fff + uint32_t rc2_evt4op2 : 6; // @ 25 -- 20 # 0xfc0fffff + uint32_t rc2_evt4op1 : 6; // @ 31 -- 26 # 0x3ffffff }; } r0xc830; // @ 0x1830 uint8_t pad16[0x4]; union { uint32_t value; struct { - uint32_t set_0x100_54 : 19; // @ 18 -- 0 # 0xfff80000 + uint32_t rc2_reflevofdmthd : 19; // @ 18 -- 0 # 0xfff80000 uint32_t pad0 : 12; - uint32_t set_0x1_53 : 1; // @ 31 -- 31 # 0x7fffffff + uint32_t rc2_reflevofdmthd_en : 1; // @ 31 -- 31 # 0x7fffffff }; } r0xc838; // @ 0x1838 union { uint32_t value; struct { - uint32_t set_0x17c_56 : 20; // @ 19 -- 0 # 0xfff00000 + uint32_t rc2_reflevdsssthd : 20; // @ 19 -- 0 # 0xfff00000 uint32_t pad0 : 11; - uint32_t set_0x1_55 : 1; // @ 31 -- 31 # 0x7fffffff + uint32_t rc2_reflevdsssthd_en : 1; // @ 31 -- 31 # 0x7fffffff }; } r0xc83c; // @ 0x183c union { uint32_t value; struct { - uint32_t set_0x100_58 : 22; // @ 21 -- 0 # 0xffc00000 + uint32_t rc2_reflevdssscontthd : 22; // @ 21 -- 0 # 0xffc00000 uint32_t pad0 : 9; - uint32_t set_0x1_57 : 1; // @ 31 -- 31 # 0x7fffffff + uint32_t rc2_reflevdssscontthd_en : 1; // @ 31 -- 31 # 0x7fffffff }; } r0xc840; // @ 0x1840 }; diff --git a/src/include/phy/bz_phy.h b/src/include/phy/bz_phy.h index a2ba2df..2259841 100644 --- a/src/include/phy/bz_phy.h +++ b/src/include/phy/bz_phy.h @@ -7,41 +7,41 @@ typedef union { uint32_t value; struct { uint32_t pad0 : 23; - uint32_t set_0x1_67 : 1; // @ 23 -- 23 # 0xff7fffff - uint32_t set_0x8_68 : 8; // @ 31 -- 24 # 0xffffff + uint32_t bz_phy_tx_rampup_fm_on : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t bz_phy_tx_rampup_time_us : 8; // @ 31 -- 24 # 0xffffff }; } r0x2808; // @ 0x808 union { uint32_t value; struct { - uint32_t set_0x0_71 : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t bz_phy_tx_rampdn_pad0_time_us : 8; // @ 7 -- 0 # 0xffffff00 uint32_t pad0 : 15; - uint32_t set_0x1_69 : 1; // @ 23 -- 23 # 0xff7fffff - uint32_t set_0x4_70 : 8; // @ 31 -- 24 # 0xffffff + uint32_t bz_phy_tx_rampdn_fm_on : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t bz_phy_tx_rampdn_time_us : 8; // @ 31 -- 24 # 0xffffff }; } r0x280c; // @ 0x80c union { uint32_t value; struct { - uint32_t set_0x0_76 : 1; // @ 0 -- 0 # 0xfffffffe - uint32_t set_0x1_77 : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t bz_phy_rx_dfe_notch_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t bz_phy_rx_dfe_toc_en : 1; // @ 1 -- 1 # 0xfffffffd }; } r0x2810; // @ 0x810 uint8_t pad1[0x40]; union { uint32_t value; struct { - uint32_t set_0x1e_75 : 8; // @ 7 -- 0 # 0xffffff00 - uint32_t set_0x20_72 : 8; // @ 15 -- 8 # 0xffff00ff - uint32_t set_0xa_74 : 8; // @ 23 -- 16 # 0xff00ffff - uint32_t set_0x1e_73 : 8; // @ 31 -- 24 # 0xffffff + uint32_t bz_phy_rx_proc_time_viterbi_us : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t bz_phy_rx_proc_time_mlsd_us : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t bz_phy_rx_proc_time_eq_us : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t bz_phy_rx_proc_time_direct_us : 8; // @ 31 -- 24 # 0xffffff }; } r0x2854; // @ 0x854 uint8_t pad2[0x454]; union { uint32_t value; struct { - uint32_t set_0x4_78 : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t bz_agc_rbb_ind_min : 5; // @ 4 -- 0 # 0xffffffe0 }; } r0x2cac; // @ 0xcac }; diff --git a/src/include/phy/mdm.h b/src/include/phy/mdm.h index 8bdd17f..62a5a81 100644 --- a/src/include/phy/mdm.h +++ b/src/include/phy/mdm.h @@ -116,9 +116,9 @@ typedef union { uint32_t pad0 : 27; uint32_t resetto1 : 1; // @ 27 -- 27 # 0xf7ffffff uint32_t pad1 : 1; - uint32_t set1beforewriteagcmem : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t mdm_agcmemclkforce : 1; // @ 29 -- 29 # 0xdfffffff }; - } r874; // @ 0x874 + } r0x874; // @ 0x874 uint8_t pad6[0x10]; union { uint32_t value; From 80069a967bf92bc6e1bfc4db1307371a29c4b985 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sat, 24 Jul 2021 04:31:36 -0500 Subject: [PATCH 030/148] import other DWARF info and done --- script/manualext.py | 70 ++++++++++++++++++------------------- src/include/phy/agc.h | 8 ++--- src/include/phy/dma.h | 10 +++--- src/include/phy/mdm.h | 34 +++++++++--------- src/include/phy/sysctrl.h | 12 ++++--- src/include/phy/sysctrl92.h | 2 +- 6 files changed, 69 insertions(+), 67 deletions(-) diff --git a/script/manualext.py b/script/manualext.py index 0912ee3..6693cb3 100755 --- a/script/manualext.py +++ b/script/manualext.py @@ -12,33 +12,33 @@ Field('txcbwmax', 0xfcffffff) # Channel bandwidth Field('txnssmax', 0xffffff8f) # number of spatial streams Field('ntxmax', 0xff8fffff) # tx chan? -Field('v18', 0xfffffeff) # some switch? DAT_44c00000>>18 +Field('txldpcen', 0xfffffeff) # some switch? DAT_44c00000>>18 Field('vht', 0xfffffffd) # very high throughput -Field('v31', 0xfffeffff) # some switch? DAT_44c00000>>31 +Field('txmumimoen', 0xfffeffff) # some switch? DAT_44c00000>>31 Reg('rxchan', 0x44c00820) Field('rxcbwmax', 0xfcffffff) # Channel bandwidth Field('rxnssmax', 0xffffff8f) # number of spatial streams # Field('nrxmax', 0xff8fffff) # not exists -Field('v19', 0xfffffeff) # some switch? DAT_44c00000>>19 -Field('vht', 0xfffffffd) # very high throughput -Field('v30', 0xfffeffff) # some switch? DAT_44c00000>>30 -Field('_v30', 0xffefffff) # some switch? DAT_44c00000>>30 -FieldBit('reset', 0) # set 1 in phy_hw_set_channel for.. reset? +Field('rxldpcen', 0xfffffeff) # some switch? DAT_44c00000>>19 +Field('rxvhten', 0xfffffffd) # very high throughput +Field('rxmumimoen', 0xfffeffff) # some switch? DAT_44c00000>>30 +Field('rxmumimoapeplenen', 0xffefffff) # some switch? DAT_44c00000>>30 +FieldBit('rxdsssen', 0) # set 1 in phy_hw_set_channel for.. reset? Field('rxndpnstsmax', 0xffff8fff) Reg('version', 0x44c00000) FieldBit('vht', 31-9) FieldBit('nss', 8, 4) # phy_get_nss (nss + 1) -FieldBit('rxndpnstsmax', 0xc, 4) -FieldBit('v18', 0x12) -FieldBit('v19', 0x13) +FieldBit('nsts', 0xc, 4) +FieldBit('ldpcenc', 0x12) +FieldBit('ldpcdec', 0x13) FieldBit('mu_mimo_rx', 0x1e) FieldBit('mu_mimo_tx', 0x1f) FieldBit('ldpctx', 0x1a) FieldBit('ldpcrx', 0x1b) FieldBit('ntx', 4, 4) # phy_get_ntx (ntx + 1) -FieldBit('txcbwmax', 0x18, 2) +FieldBit('chbw', 0x18, 2) FieldBit('bfmee_supported', 0x1c) FieldBit('bfmer_supported', 0x1d) @@ -50,9 +50,9 @@ FieldBit('FSMSWRESET', 4) FieldBit('MDMSWRESET', 0) -Reg('TXCTRL0', 0x44c00838) -Reg('TXCTRL1', 0x44c0088c) -Reg('TXCTRL3', 0x44c00898) +Reg('txstartdelay', 0x44c00838) +Reg('txctrl1', 0x44c0088c) +Reg('txctrl3', 0x44c00898) Reg('TBECTRL0', 0x44c00858) Field('tbe_count_adjust_20', 0xffffff00) @@ -62,8 +62,8 @@ Field('WAITHTSTF', 0xffffff80) Reg('r834', 0x44c00834) -Field('set60h', 0x00ffffff) -FieldBit('set1', 0) +Field('tddchtstfmargin', 0x00ffffff) +FieldBit('rxtdctrl1', 0) Reg('SMOOTHCTRL', 0x44c00818) FieldBit('TDCYCROTVAL20', 0, 8) @@ -93,7 +93,7 @@ Reg('rxctrl1', 0x44c0083c) # reset to 0x4920492 Reg('r0x874', 0x44c00874) -Field('resetto1', 0xf7ffffff) +Field('rcclkforce', 0xf7ffffff) Field('mdm_agcmemclkforce', 0xdfffffff) #print('\n'.join(GenSVD())) @@ -116,9 +116,9 @@ Reg('RWNXAGCCNTL', 0x44c0b390) -Field('set1', 0xfffffffc) +Field('combpathsel', 0xfffffffc) Field('agcfsmreset', 0xffffefff) # set 1 before agc mem, maybe - +Field('rifsdeten', 0xfffffbff) Reg('riu_rwnxagcaci20marg0', 0x44c0b340) Reg('riu_rwnxagcaci20marg1', 0x44c0b344) Reg('riu_rwnxagcaci20marg2', 0x44c0b348) @@ -132,13 +132,14 @@ Reg('irqmacccatimeouten', 0x44c0b414) Field('set1', 0xFFFFFEFF) -Reg('r41c', 0x44c0b41c) +Reg('rwnxmacintstatmasked', 0x44c0b41c) FieldBit('needreset', 8) # guess -Reg('r420_copy41c', 0x44c0b420) + +Reg('rwnxmacintack', 0x44c0b420) Reg('rc218', 0x44c0c218) -Field('set0', 0xffff0000) +Field('txhbf20coeffsel', 0xffff0000) Buf('rxgain_offset_vs_temperature', 0x44c0c080, 0x44c0c088, 1) @@ -347,13 +348,13 @@ def getregs(fname, pattern='name'): peris['dma'] = Peripheral(peripheral('dma', 0x44a00000, 0x1000)) -Reg('status', 0x44a00024) +Reg('int_status', 0x44a00024) Field("TX", 0x1f) FieldBit("RXHeader", 5) ## guess FieldBit("RXPayload", 6) ## guess FieldBit("b8", 8) -Reg('tx_reset', 0x44a00020) # my guess, setting of r20 should reset 0x24?? +Reg('int_ack', 0x44a00020) # my guess, setting of r20 should reset 0x24?? # kind like response... FieldBit("b8", 8) # set at txl_cfm_dma_int_handler FieldBit("b7", 7) # set at ipc_emb_dbg_dma_int_handler @@ -362,9 +363,10 @@ def getregs(fname, pattern='name'): Field("TX", 0x1f) Reg("dma_status", 0x44a00010) -Field("busyatffff", 0xffff) +Field("dma_status_oft_free", 0xffff) # my guess!! +# access with dma_lli_counter_get(reg_idx) Reg('TX_BCN', 0x44a00080) FieldBit('bridgedmacnt', 0, 16) Reg('TX_AC_0', 0x44a00084) @@ -377,9 +379,9 @@ def getregs(fname, pattern='name'): FieldBit('bridgedmacnt', 0, 16) Reg('LinkListItem0', 0x44a000a4) -FieldBit("lli", 0, 16) +FieldBit("counter", 0, 16) Reg('LinkListItem1', 0x44a000ac) -FieldBit("lli", 0, 16) +FieldBit("counter", 0, 16) #open('../src/include/phy/dma.h', 'w').write('\n'.join(GenHeader())) #print('\n'.join(GenHeader())) @@ -390,16 +392,14 @@ def getregs(fname, pattern='name'): peris['sysctrl'] = Peripheral(peripheral('sysctrl', 0x44900000, 0x1000)) Reg('time', 0x44900084) FieldBit('time_greater_on_bit12', 0) -Reg("sysctrl_r68", 0x44900068) # set to 0x8000000c for init -Reg("sysctrl_re0", 0x449000e0) # or with 0x1ff00 -Field("set1", (~0x1ff00) & 0xffffffff) +Reg("diag_conf", 0x44900068) # set to 0x8000000c for init +Field("diag_sel", 0xffff0000) +Reg("misc_cntl", 0x449000e0) # or with 0x1ff00 +Field("set1", (~0x1ff00) & 0xffffffff) -## two regs for helper_record_all_states -Reg("r068", 0x44900068) -Field("set14", 0xffff0000) -Reg("r074", 0x44900068) # set to b09 +Reg("r074", 0x44900074) # set to b09 #open('../src/include/phy/sysctrl.h', 'w').write('\n'.join(GenHeader())) #print('\n'.join(GenHeader())) @@ -410,7 +410,7 @@ def getregs(fname, pattern='name'): ## wtf is this??? peris['sysctrl92'] = Peripheral(peripheral('sysctrl92', 0x44920000, 0x1000)) -Reg("set5010001f", 0x44920004) +Reg("ptr_config", 0x44920004) #open('../src/include/phy/sysctrl92.h', 'w').write('\n'.join(GenHeader())) #print('\n'.join(GenHeader())) diff --git a/src/include/phy/agc.h b/src/include/phy/agc.h index 15fc4a8..465cc73 100644 --- a/src/include/phy/agc.h +++ b/src/include/phy/agc.h @@ -112,7 +112,7 @@ typedef union { union { uint32_t value; struct { - uint32_t set1 : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t combpathsel : 2; // @ 1 -- 0 # 0xfffffffc uint32_t pad0 : 6; uint32_t riu_rifsdeten : 1; // @ 8 -- 8 # 0xfffffeff uint32_t pad1 : 1; @@ -183,8 +183,8 @@ typedef union { uint32_t pad0 : 8; uint32_t needreset : 1; // @ 8 -- 8 # 0xfffffeff }; - } r41c; // @ 0x41c - uint32_t r420_copy41c; // @ 0x420 + } rwnxmacintstatmasked; // @ 0x41c + uint32_t rwnxmacintack; // @ 0x420 uint8_t pad9[0xdc]; union { uint32_t value; @@ -223,7 +223,7 @@ typedef union { union { uint32_t value; struct { - uint32_t set0 : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t txhbf20coeffsel : 16; // @ 15 -- 0 # 0xffff0000 }; } rc218; // @ 0x1218 uint8_t pad14[0x5f8]; diff --git a/src/include/phy/dma.h b/src/include/phy/dma.h index 708712e..9525c12 100644 --- a/src/include/phy/dma.h +++ b/src/include/phy/dma.h @@ -7,7 +7,7 @@ typedef union { uint32_t value; struct { uint32_t pad0 : 16; - uint32_t busyatffff : 16; // @ 31 -- 16 # 0xffff + uint32_t dma_status_oft_free : 16; // @ 31 -- 16 # 0xffff }; } dma_status; // @ 0x10 uint8_t pad1[0xc]; @@ -21,7 +21,7 @@ typedef union { uint32_t b8 : 1; // @ 8 -- 8 # 0xfffffeff uint32_t TX : 27; // @ 31 -- 5 # 0x1f }; - } tx_reset; // @ 0x20 + } int_ack; // @ 0x20 union { uint32_t value; struct { @@ -32,7 +32,7 @@ typedef union { uint32_t b8 : 1; // @ 8 -- 8 # 0xfffffeff uint32_t TX : 27; // @ 31 -- 5 # 0x1f }; - } status; // @ 0x24 + } int_status; // @ 0x24 uint8_t pad2[0x58]; union { uint32_t value; @@ -68,14 +68,14 @@ typedef union { union { uint32_t value; struct { - uint32_t lli : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t counter : 16; // @ 15 -- 0 # 0xffff0000 }; } LinkListItem0; // @ 0xa4 uint8_t pad4[0x4]; union { uint32_t value; struct { - uint32_t lli : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t counter : 16; // @ 15 -- 0 # 0xffff0000 }; } LinkListItem1; // @ 0xac }; diff --git a/src/include/phy/mdm.h b/src/include/phy/mdm.h index 62a5a81..341242e 100644 --- a/src/include/phy/mdm.h +++ b/src/include/phy/mdm.h @@ -8,14 +8,14 @@ typedef union { uint32_t pad0 : 4; uint32_t ntx : 4; // @ 7 -- 4 # 0xffffff0f uint32_t nss : 4; // @ 11 -- 8 # 0xfffff0ff - uint32_t rxndpnstsmax : 4; // @ 15 -- 12 # 0xffff0fff + uint32_t nsts : 4; // @ 15 -- 12 # 0xffff0fff uint32_t pad1 : 2; - uint32_t v18 : 1; // @ 18 -- 18 # 0xfffbffff - uint32_t v19 : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t ldpcenc : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t ldpcdec : 1; // @ 19 -- 19 # 0xfff7ffff uint32_t pad2 : 2; uint32_t vht : 1; // @ 22 -- 22 # 0xffbfffff uint32_t pad3 : 1; - uint32_t txcbwmax : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t chbw : 2; // @ 25 -- 24 # 0xfcffffff uint32_t ldpctx : 1; // @ 26 -- 26 # 0xfbffffff uint32_t ldpcrx : 1; // @ 27 -- 27 # 0xf7ffffff uint32_t bfmee_supported : 1; // @ 28 -- 28 # 0xefffffff @@ -49,18 +49,18 @@ typedef union { union { uint32_t value; struct { - uint32_t reset : 1; // @ 0 -- 0 # 0xfffffffe - uint32_t vht : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t rxdsssen : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t rxvhten : 1; // @ 1 -- 1 # 0xfffffffd uint32_t pad0 : 2; uint32_t rxnssmax : 3; // @ 6 -- 4 # 0xffffff8f uint32_t pad1 : 1; - uint32_t v19 : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t rxldpcen : 1; // @ 8 -- 8 # 0xfffffeff uint32_t pad2 : 3; uint32_t rxndpnstsmax : 3; // @ 14 -- 12 # 0xffff8fff uint32_t pad3 : 1; - uint32_t v30 : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t rxmumimoen : 1; // @ 16 -- 16 # 0xfffeffff uint32_t pad4 : 3; - uint32_t _v30 : 1; // @ 20 -- 20 # 0xffefffff + uint32_t rxmumimoapeplenen : 1; // @ 20 -- 20 # 0xffefffff uint32_t pad5 : 3; uint32_t rxcbwmax : 2; // @ 25 -- 24 # 0xfcffffff }; @@ -73,9 +73,9 @@ typedef union { uint32_t pad1 : 2; uint32_t txnssmax : 3; // @ 6 -- 4 # 0xffffff8f uint32_t pad2 : 1; - uint32_t v18 : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t txldpcen : 1; // @ 8 -- 8 # 0xfffffeff uint32_t pad3 : 7; - uint32_t v31 : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t txmumimoen : 1; // @ 16 -- 16 # 0xfffeffff uint32_t pad4 : 3; uint32_t ntxmax : 3; // @ 22 -- 20 # 0xff8fffff uint32_t pad5 : 1; @@ -93,12 +93,12 @@ typedef union { union { uint32_t value; struct { - uint32_t set1 : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t rxtdctrl1 : 1; // @ 0 -- 0 # 0xfffffffe uint32_t pad0 : 23; - uint32_t set60h : 8; // @ 31 -- 24 # 0xffffff + uint32_t tddchtstfmargin : 8; // @ 31 -- 24 # 0xffffff }; } r834; // @ 0x834 - uint32_t TXCTRL0; // @ 0x838 + uint32_t txstartdelay; // @ 0x838 uint32_t rxctrl1; // @ 0x83c uint8_t pad3[0x18]; union { @@ -114,7 +114,7 @@ typedef union { uint32_t value; struct { uint32_t pad0 : 27; - uint32_t resetto1 : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t rcclkforce : 1; // @ 27 -- 27 # 0xf7ffffff uint32_t pad1 : 1; uint32_t mdm_agcmemclkforce : 1; // @ 29 -- 29 # 0xdfffffff }; @@ -132,9 +132,9 @@ typedef union { uint32_t AGCSWRESET : 1; // @ 12 -- 12 # 0xffffefff }; } swreset; // @ 0x888 - uint32_t TXCTRL1; // @ 0x88c + uint32_t txctrl1; // @ 0x88c uint8_t pad7[0x8]; - uint32_t TXCTRL3; // @ 0x898 + uint32_t txctrl3; // @ 0x898 uint32_t rxframeviolationmask; // @ 0x89c uint8_t pad8[0x2784]; union { diff --git a/src/include/phy/sysctrl.h b/src/include/phy/sysctrl.h index eeb0009..208b8c3 100644 --- a/src/include/phy/sysctrl.h +++ b/src/include/phy/sysctrl.h @@ -6,24 +6,26 @@ typedef union { union { uint32_t value; struct { - uint32_t set14 : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t diag_sel : 16; // @ 15 -- 0 # 0xffff0000 }; - } sysctrl_r68; // @ 0x68 - uint8_t pad1[0x18]; + } diag_conf; // @ 0x68 + uint8_t pad1[0x8]; + uint32_t r074; // @ 0x74 + uint8_t pad2[0xc]; union { uint32_t value; struct { uint32_t time_greater_on_bit12 : 1; // @ 0 -- 0 # 0xfffffffe }; } time; // @ 0x84 - uint8_t pad2[0x58]; + uint8_t pad3[0x58]; union { uint32_t value; struct { uint32_t pad0 : 8; uint32_t set1 : 9; // @ 16 -- 8 # 0xfffe00ff }; - } sysctrl_re0; // @ 0xe0 + } misc_cntl; // @ 0xe0 }; } sysctrl_regs; #define SYSCTRL_BASE 0x44900000 diff --git a/src/include/phy/sysctrl92.h b/src/include/phy/sysctrl92.h index 53c2e7c..a137b6b 100644 --- a/src/include/phy/sysctrl92.h +++ b/src/include/phy/sysctrl92.h @@ -3,7 +3,7 @@ typedef union { uint8_t pad[0x1000]; struct { uint8_t pad0[0x4]; - uint32_t set5010001f; // @ 0x4 + uint32_t ptr_config; // @ 0x4 }; } sysctrl92_regs; #define SYSCTRL92_BASE 0x44920000 From 16d67b82d78d900835cef2ec91a96f386de27563 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sat, 24 Jul 2021 04:34:09 -0500 Subject: [PATCH 031/148] padding to 32 --- script/reglib.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/script/reglib.py b/script/reglib.py index 05a4fe7..7db82d2 100755 --- a/script/reglib.py +++ b/script/reglib.py @@ -97,6 +97,8 @@ def genHeader(self): padId = padId + 1 s.extend(ident(i.genHeader(), 2, '\t')) currentBit = i.msb + 1 + if currentBit != 32: + s.append(f'\t\tuint32_t pad{padId} : {32 - currentBit};') s.extend([ "\t};", @@ -290,6 +292,12 @@ def FieldBit(name, bit, len=1): context.r.addField(name, (~(((2**len)-1)< Date: Sat, 24 Jul 2021 04:34:28 -0500 Subject: [PATCH 032/148] done --- src/include/phy/agc.h | 21 ++++++++++++++++ src/include/phy/bz_phy.h | 2 ++ src/include/phy/dma.h | 7 ++++++ src/include/phy/mac_core.h | 50 ++++++++++++++++++++++++++++++++++++++ src/include/phy/mac_pl.h | 23 ++++++++++++++++++ src/include/phy/mdm.h | 9 +++++++ src/include/phy/sysctrl.h | 3 +++ 7 files changed, 115 insertions(+) diff --git a/src/include/phy/agc.h b/src/include/phy/agc.h index 465cc73..c89c8ad 100644 --- a/src/include/phy/agc.h +++ b/src/include/phy/agc.h @@ -7,6 +7,7 @@ typedef union { struct { uint32_t pad0 : 21; uint32_t iqcomp : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t pad1 : 10; }; } r000; // @ 0x0 uint32_t activeant; // @ 0x4 @@ -18,6 +19,7 @@ typedef union { uint32_t riu_adcpowmindbm : 1; // @ 1 -- 1 # 0xfffffffd uint32_t riu_vpeakadcqdbv : 1; // @ 2 -- 2 # 0xfffffffb uint32_t riu_fe40gain : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pad0 : 28; }; } r0xb110; // @ 0x110 uint8_t pad1[0x4]; @@ -37,6 +39,7 @@ typedef union { uint32_t riu_sathighthrdbv : 6; // @ 21 -- 16 # 0xffc0ffff uint32_t pad2 : 2; uint32_t riu_satdelay50ns : 5; // @ 28 -- 24 # 0xe0ffffff + uint32_t pad3 : 3; }; } r0xb364; // @ 0x364 union { @@ -45,6 +48,7 @@ typedef union { uint32_t riu_crossupthrqdbm : 10; // @ 9 -- 0 # 0xfffffc00 uint32_t pad0 : 2; uint32_t riu_crossdnthrqdbm : 10; // @ 21 -- 12 # 0xffc00fff + uint32_t pad1 : 10; }; } r0xb368; // @ 0x368 union { @@ -55,6 +59,7 @@ typedef union { uint32_t pad0 : 5; uint32_t riu_rampdngapqdb : 8; // @ 23 -- 16 # 0xff00ffff uint32_t riu_rampdnndlindex : 3; // @ 26 -- 24 # 0xf8ffffff + uint32_t pad1 : 5; }; } RWNXAGCRAMP; // @ 0x36c union { @@ -62,6 +67,7 @@ typedef union { struct { uint32_t pad0 : 16; uint32_t riu_adcpowdisthrdbv : 7; // @ 22 -- 16 # 0xff80ffff + uint32_t pad1 : 9; }; } r0xb370; // @ 0x370 uint8_t pad4[0xc]; @@ -121,6 +127,7 @@ typedef union { uint32_t agcfsmreset : 1; // @ 12 -- 12 # 0xffffefff uint32_t pad3 : 3; uint32_t riu_htstfgainen : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad4 : 15; }; } RWNXAGCCNTL; // @ 0x390 union { @@ -128,6 +135,7 @@ typedef union { struct { uint32_t pad0 : 16; uint32_t riu_vpeakadcqdbv : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t pad1 : 8; }; } r0xb394; // @ 0x394 union { @@ -135,6 +143,7 @@ typedef union { struct { uint32_t pad0 : 8; uint32_t riu_adcpowmindbm : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t pad1 : 16; }; } r0xb398; // @ 0x398 uint8_t pad5[0x4]; @@ -142,6 +151,7 @@ typedef union { uint32_t value; struct { uint32_t riu_inbdpowmindbm : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pad0 : 24; }; } r0xb3a0; // @ 0x3a0 union { @@ -149,6 +159,7 @@ typedef union { struct { uint32_t riu_fe20gain : 8; // @ 7 -- 0 # 0xffffff00 uint32_t riu_fe40gain : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t pad0 : 16; }; } r0xb3a4; // @ 0x3a4 uint8_t pad6[0x14]; @@ -166,6 +177,7 @@ typedef union { uint32_t value; struct { uint32_t riu_adcpowsupthrdbm : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pad0 : 24; }; } r0xb3c4; // @ 0x3c4 uint8_t pad7[0x4c]; @@ -174,6 +186,7 @@ typedef union { struct { uint32_t pad0 : 8; uint32_t set1 : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pad1 : 23; }; } irqmacccatimeouten; // @ 0x414 uint8_t pad8[0x4]; @@ -182,6 +195,7 @@ typedef union { struct { uint32_t pad0 : 8; uint32_t needreset : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pad1 : 23; }; } rwnxmacintstatmasked; // @ 0x41c uint32_t rwnxmacintack; // @ 0x420 @@ -191,6 +205,7 @@ typedef union { struct { uint32_t pad0 : 12; uint32_t riu_fe20gain : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t pad1 : 18; }; } r0xb500; // @ 0x500 uint8_t pad10[0xb1c]; @@ -199,6 +214,7 @@ typedef union { struct { uint32_t pad0 : 16; uint32_t riu_htstfgainen : 10; // @ 25 -- 16 # 0xfc00ffff + uint32_t pad1 : 6; }; } r0xc020; // @ 0x1020 uint8_t pad11[0x1c]; @@ -208,6 +224,7 @@ typedef union { uint32_t pad0 : 15; uint32_t rc2_rx0_vga_idx_min : 5; // @ 19 -- 15 # 0xfff07fff uint32_t rc2_rx0_vga_idx_max : 5; // @ 24 -- 20 # 0xfe0fffff + uint32_t pad1 : 7; }; } r0xc040; // @ 0x1040 union { @@ -215,6 +232,7 @@ typedef union { struct { uint32_t rc2_rx0_lna_idx_min : 8; // @ 7 -- 0 # 0xffffff00 uint32_t rc2_rx0_lna_idx_max : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t pad0 : 16; }; } r0xc044; // @ 0x1044 uint8_t pad12[0x38]; @@ -224,6 +242,7 @@ typedef union { uint32_t value; struct { uint32_t txhbf20coeffsel : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } rc218; // @ 0x1218 uint8_t pad14[0x5f8]; @@ -232,6 +251,7 @@ typedef union { struct { uint32_t rc2_pkdet_mode : 2; // @ 1 -- 0 # 0xfffffffc uint32_t rc2_pkdet_cnt_thr : 4; // @ 5 -- 2 # 0xffffffc3 + uint32_t pad0 : 26; }; } r0xc814; // @ 0x1814 uint8_t pad15[0x14]; @@ -244,6 +264,7 @@ typedef union { uint32_t rc2_inbdpowinfthr_adj_en : 1; // @ 11 -- 11 # 0xfffff7ff uint32_t pad1 : 3; uint32_t rc2_inbdpowfastvalid_cnt : 9; // @ 23 -- 15 # 0xff007fff + uint32_t pad2 : 8; }; } r0xc82c; // @ 0x182c union { diff --git a/src/include/phy/bz_phy.h b/src/include/phy/bz_phy.h index 2259841..f44f20d 100644 --- a/src/include/phy/bz_phy.h +++ b/src/include/phy/bz_phy.h @@ -25,6 +25,7 @@ typedef union { struct { uint32_t bz_phy_rx_dfe_notch_en : 1; // @ 0 -- 0 # 0xfffffffe uint32_t bz_phy_rx_dfe_toc_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t pad0 : 30; }; } r0x2810; // @ 0x810 uint8_t pad1[0x40]; @@ -42,6 +43,7 @@ typedef union { uint32_t value; struct { uint32_t bz_agc_rbb_ind_min : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t pad0 : 27; }; } r0x2cac; // @ 0xcac }; diff --git a/src/include/phy/dma.h b/src/include/phy/dma.h index 9525c12..9c4e2fd 100644 --- a/src/include/phy/dma.h +++ b/src/include/phy/dma.h @@ -38,30 +38,35 @@ typedef union { uint32_t value; struct { uint32_t bridgedmacnt : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } TX_BCN; // @ 0x80 union { uint32_t value; struct { uint32_t bridgedmacnt : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } TX_AC_0; // @ 0x84 union { uint32_t value; struct { uint32_t bridgedmacnt : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } TX_AC_1; // @ 0x88 union { uint32_t value; struct { uint32_t bridgedmacnt : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } TX_AC_2; // @ 0x8c union { uint32_t value; struct { uint32_t bridgedmacnt : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } TX_AC_3; // @ 0x90 uint8_t pad3[0x10]; @@ -69,6 +74,7 @@ typedef union { uint32_t value; struct { uint32_t counter : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } LinkListItem0; // @ 0xa4 uint8_t pad4[0x4]; @@ -76,6 +82,7 @@ typedef union { uint32_t value; struct { uint32_t counter : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } LinkListItem1; // @ 0xac }; diff --git a/src/include/phy/mac_core.h b/src/include/phy/mac_core.h index c434fec..f869d75 100644 --- a/src/include/phy/mac_core.h +++ b/src/include/phy/mac_core.h @@ -28,6 +28,7 @@ typedef union { uint32_t coex : 1; // @ 14 -- 14 # 0xffffbfff uint32_t pad1 : 1; uint32_t mac80211MHFormat : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad2 : 15; }; } VERSION_1; // @ 0x4 union { @@ -37,12 +38,14 @@ typedef union { uint32_t ieRelease : 1; // @ 7 -- 7 # 0xffffff7f uint32_t releaseNumber : 6; // @ 13 -- 8 # 0xffffc0ff uint32_t phaseNumber : 3; // @ 16 -- 14 # 0xfffe3fff + uint32_t pad0 : 15; }; } VERSION_2; // @ 0x8 union { uint32_t value; struct { uint32_t bitmapCnt : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } BITMAP_CNT; // @ 0xc union { @@ -55,6 +58,7 @@ typedef union { uint32_t value; struct { uint32_t macAddrHigh : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } MAC_ADDR_HI; // @ 0x14 union { @@ -67,6 +71,7 @@ typedef union { uint32_t value; struct { uint32_t macAddrHighMask : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } MAC_ADDR_HI_MASK; // @ 0x1c union { @@ -79,6 +84,7 @@ typedef union { uint32_t value; struct { uint32_t bssIDHigh : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } BSS_ID_HI; // @ 0x24 union { @@ -91,6 +97,7 @@ typedef union { uint32_t value; struct { uint32_t bssIDHighMask : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } BSS_ID_HI_MASK; // @ 0x2c uint8_t pad0[0x8]; @@ -99,12 +106,14 @@ typedef union { struct { uint32_t currentState : 4; // @ 3 -- 0 # 0xfffffff0 uint32_t nextState : 4; // @ 7 -- 4 # 0xffffff0f + uint32_t pad0 : 24; }; } STATE_CNTRL; // @ 0x38 union { uint32_t value; struct { uint32_t probeDelay : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } SCAN_CNTRL; // @ 0x3c uint8_t pad1[0x4]; @@ -138,6 +147,7 @@ typedef union { uint32_t tsfUpdatedBySW : 1; // @ 24 -- 24 # 0xfeffffff uint32_t tsfMgtDisable : 1; // @ 25 -- 25 # 0xfdffffff uint32_t rxRIFSEn : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t pad2 : 5; }; } MAC_CNTRL_1; // @ 0x4c uint8_t pad3[0x4]; @@ -154,6 +164,7 @@ typedef union { uint32_t baPSBitmapReset : 1; // @ 7 -- 7 # 0xffffff7f uint32_t pad0 : 8; uint32_t rxFlowCntrlEn : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad1 : 15; }; } MAC_ERR_REC_CNTRL; // @ 0x54 union { @@ -163,6 +174,7 @@ typedef union { uint32_t errInRxLevel1 : 1; // @ 1 -- 1 # 0xfffffffd uint32_t errInTxRxLevel2 : 1; // @ 2 -- 2 # 0xfffffffb uint32_t errInHWLevel3 : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pad0 : 28; }; } MAC_ERR_SET_STATUS; // @ 0x58 union { @@ -172,6 +184,7 @@ typedef union { uint32_t clearErrInRxLevel1 : 1; // @ 1 -- 1 # 0xfffffffd uint32_t clearErrInTxRxLevel2 : 1; // @ 2 -- 2 # 0xfffffffb uint32_t clearErrInHWLevel3 : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pad0 : 28; }; } MAC_ERR_CLEAR_STATUS; // @ 0x5c union { @@ -226,6 +239,7 @@ typedef union { uint32_t bcnUpdateOffset : 8; // @ 7 -- 0 # 0xffffff00 uint32_t timOffset : 8; // @ 15 -- 8 # 0xffff00ff uint32_t aid : 12; // @ 27 -- 16 # 0xf000ffff + uint32_t pad0 : 4; }; } BCN_CNTRL_2; // @ 0x68 uint8_t pad4[0x24]; @@ -242,6 +256,7 @@ typedef union { uint32_t value; struct { uint32_t cfpMaxDuration : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } DTIM_CFP_2; // @ 0x94 union { @@ -249,6 +264,7 @@ typedef union { struct { uint32_t dot11ShortRetryLimit : 8; // @ 7 -- 0 # 0xffffff00 uint32_t dot11LongRetryLimit : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t pad0 : 16; }; } RETRY_LIMITS; // @ 0x98 union { @@ -258,6 +274,7 @@ typedef union { uint32_t bbServiceB : 8; // @ 23 -- 16 # 0xff00ffff uint32_t pad0 : 2; uint32_t maxPHYNtx : 3; // @ 28 -- 26 # 0xe3ffffff + uint32_t pad1 : 3; }; } BB_SERVICE; // @ 0x9c union { @@ -265,6 +282,7 @@ typedef union { struct { uint32_t ofdmMaxPwrLevel : 8; // @ 7 -- 0 # 0xffffff00 uint32_t dsssMaxPwrLevel : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t pad0 : 16; }; } MAX_POWER_LEVEL; // @ 0xa0 uint8_t pad5[0x8]; @@ -302,6 +320,7 @@ typedef union { uint32_t value; struct { uint32_t macAddrRAMHigh : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } ENCR_MAC_ADDR_HIGH; // @ 0xc0 union { @@ -348,6 +367,7 @@ typedef union { uint32_t value; struct { uint32_t bssBasicRateSet : 12; // @ 11 -- 0 # 0xfffff000 + uint32_t pad0 : 20; }; } RATES; // @ 0xdc union { @@ -364,6 +384,7 @@ typedef union { uint32_t macCoreClkFreq : 8; // @ 7 -- 0 # 0xffffff00 uint32_t txRFDelayInMACClk : 10; // @ 17 -- 8 # 0xfffc00ff uint32_t txChainDelayInMACClk : 10; // @ 27 -- 18 # 0xf003ffff + uint32_t pad0 : 4; }; } TIMINGS_1; // @ 0xe4 union { @@ -371,6 +392,7 @@ typedef union { struct { uint32_t slotTime : 8; // @ 7 -- 0 # 0xffffff00 uint32_t slotTimeInMACClk : 16; // @ 23 -- 8 # 0xff0000ff + uint32_t pad0 : 8; }; } TIMINGS_2; // @ 0xe8 union { @@ -379,6 +401,7 @@ typedef union { uint32_t macProcDelayInMACClk : 10; // @ 9 -- 0 # 0xfffffc00 uint32_t txDelayRFOnInMACClk : 10; // @ 19 -- 10 # 0xfff003ff uint32_t rxRFDelayInMACClk : 10; // @ 29 -- 20 # 0xc00fffff + uint32_t pad0 : 2; }; } TIMINGS_3; // @ 0xec union { @@ -394,6 +417,7 @@ typedef union { struct { uint32_t sifsB : 8; // @ 7 -- 0 # 0xffffff00 uint32_t sifsBInMACClk : 16; // @ 23 -- 8 # 0xff0000ff + uint32_t pad0 : 8; }; } TIMINGS_5; // @ 0xf4 union { @@ -401,6 +425,7 @@ typedef union { struct { uint32_t sifsA : 8; // @ 7 -- 0 # 0xffffff00 uint32_t sifsAInMACClk : 16; // @ 23 -- 8 # 0xff0000ff + uint32_t pad0 : 8; }; } TIMINGS_6; // @ 0xf8 union { @@ -408,6 +433,7 @@ typedef union { struct { uint32_t rifs : 8; // @ 7 -- 0 # 0xffffff00 uint32_t rxCCADelay : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t pad0 : 20; }; } TIMINGS_7; // @ 0xfc union { @@ -425,6 +451,7 @@ typedef union { uint32_t txDMAProcDlyInMACClk : 10; // @ 9 -- 0 # 0xfffffc00 uint32_t rifsInMACClk : 10; // @ 19 -- 10 # 0xfff003ff uint32_t rifsTOInMACClk : 10; // @ 29 -- 20 # 0xc00fffff + uint32_t pad0 : 2; }; } TIMINGS_9; // @ 0x104 uint8_t pad7[0x4]; @@ -433,6 +460,7 @@ typedef union { struct { uint32_t edcaTriggerTimer : 8; // @ 7 -- 0 # 0xffffff00 uint32_t hccaTriggerTimer : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t pad0 : 16; }; } PROT_TRIG_TIMER; // @ 0x10c union { @@ -440,6 +468,7 @@ typedef union { struct { uint32_t txAbsoluteTimeout : 8; // @ 7 -- 0 # 0xffffff00 uint32_t txPacketTimeout : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t pad0 : 16; }; } TX_TRIGGER_TIMER; // @ 0x110 union { @@ -448,6 +477,7 @@ typedef union { uint32_t rxAbsoluteTimeout : 8; // @ 7 -- 0 # 0xffffff00 uint32_t rxPacketTimeout : 8; // @ 15 -- 8 # 0xffff00ff uint32_t rxPayloadUsedCount : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t pad0 : 8; }; } RX_TRIGGER_TIMER; // @ 0x114 union { @@ -476,6 +506,7 @@ typedef union { uint32_t value; struct { uint32_t monotonicCounterHigh2 : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } MONOTONIC_COUNTER_2_HI; // @ 0x124 union { @@ -489,6 +520,7 @@ typedef union { uint32_t value; struct { uint32_t maxAllowedLength : 20; // @ 19 -- 0 # 0xfff00000 + uint32_t pad0 : 12; }; } MAX_RX_LENGTH; // @ 0x150 uint8_t pad9[0xac]; @@ -499,6 +531,7 @@ typedef union { uint32_t cwMin0 : 4; // @ 7 -- 4 # 0xffffff0f uint32_t cwMax0 : 4; // @ 11 -- 8 # 0xfffff0ff uint32_t txOpLimit0 : 16; // @ 27 -- 12 # 0xf0000fff + uint32_t pad0 : 4; }; } EDCA_AC_0; // @ 0x200 union { @@ -508,6 +541,7 @@ typedef union { uint32_t cwMin1 : 4; // @ 7 -- 4 # 0xffffff0f uint32_t cwMax1 : 4; // @ 11 -- 8 # 0xfffff0ff uint32_t txOpLimit1 : 16; // @ 27 -- 12 # 0xf0000fff + uint32_t pad0 : 4; }; } EDCA_AC_1; // @ 0x204 union { @@ -517,6 +551,7 @@ typedef union { uint32_t cwMin2 : 4; // @ 7 -- 4 # 0xffffff0f uint32_t cwMax2 : 4; // @ 11 -- 8 # 0xfffff0ff uint32_t txOpLimit2 : 16; // @ 27 -- 12 # 0xf0000fff + uint32_t pad0 : 4; }; } EDCA_AC_2; // @ 0x208 union { @@ -526,6 +561,7 @@ typedef union { uint32_t cwMin3 : 4; // @ 7 -- 4 # 0xffffff0f uint32_t cwMax3 : 4; // @ 11 -- 8 # 0xfffff0ff uint32_t txOpLimit3 : 16; // @ 27 -- 12 # 0xf0000fff + uint32_t pad0 : 4; }; } EDCA_AC_3; // @ 0x20c uint8_t pad10[0x10]; @@ -543,6 +579,7 @@ typedef union { uint32_t pad0 : 2; uint32_t remTXOPInDurField : 1; // @ 4 -- 4 # 0xffffffef uint32_t keepTXOPOpen : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad1 : 26; }; } EDCA_CNTRL; // @ 0x224 uint8_t pad11[0x58]; @@ -558,6 +595,7 @@ typedef union { uint32_t value; struct { uint32_t quietOffset1 : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } QUIET_ELEMENT_1B; // @ 0x284 union { @@ -572,6 +610,7 @@ typedef union { uint32_t value; struct { uint32_t quietOffset2 : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } QUIET_ELEMENT_2B; // @ 0x28c union { @@ -614,12 +653,14 @@ typedef union { uint32_t startTxFormatMod : 3; // @ 26 -- 24 # 0xf8ffffff uint32_t startTxPreType : 1; // @ 27 -- 27 # 0xf7ffffff uint32_t startTxBW : 2; // @ 29 -- 28 # 0xcfffffff + uint32_t pad1 : 2; }; } START_TX_1; // @ 0x304 union { uint32_t value; struct { uint32_t durControlFrm : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } START_TX_2; // @ 0x308 union { @@ -648,6 +689,7 @@ typedef union { uint32_t dynBWEn : 1; // @ 7 -- 7 # 0xffffff7f uint32_t aPPDUMaxTime : 8; // @ 15 -- 8 # 0xffff00ff uint32_t maxSupportedBW : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad0 : 14; }; } TX_BW_CNTRL; // @ 0x310 union { @@ -655,6 +697,7 @@ typedef union { struct { uint32_t bssBasicHTMCSSetEM : 16; // @ 15 -- 0 # 0xffff0000 uint32_t bssBasicHTMCSSetUM : 6; // @ 21 -- 16 # 0xffc0ffff + uint32_t pad0 : 10; }; } HTMCS; // @ 0x314 uint8_t pad13[0x4]; @@ -662,12 +705,14 @@ typedef union { uint32_t value; struct { uint32_t bssBasicVHTMCSSet : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } VHTMCS; // @ 0x31c union { uint32_t value; struct { uint32_t supportLSTP : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 31; }; } LSTP; // @ 0x320 uint8_t pad14[0xdc]; @@ -679,6 +724,7 @@ typedef union { uint32_t coexWlanChanOffset : 1; // @ 12 -- 12 # 0xffffefff uint32_t pad1 : 3; uint32_t coexWlanChanFreq : 7; // @ 22 -- 16 # 0xff80ffff + uint32_t pad2 : 9; }; } COEX_CONTROL; // @ 0x400 union { @@ -727,12 +773,14 @@ typedef union { struct { uint32_t debugPortSel1 : 8; // @ 7 -- 0 # 0xffffff00 uint32_t debugPortSel2 : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t pad0 : 16; }; } DEBUG_PORT_SEL; // @ 0x510 union { uint32_t value; struct { uint32_t navCounter : 26; // @ 25 -- 0 # 0xfc000000 + uint32_t pad0 : 6; }; } DEBUG_NAV; // @ 0x514 union { @@ -745,6 +793,7 @@ typedef union { uint32_t activeAC : 2; // @ 17 -- 16 # 0xfffcffff uint32_t pad0 : 6; uint32_t backoffOffset : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t pad1 : 6; }; } DEBUG_CW; // @ 0x518 union { @@ -770,6 +819,7 @@ typedef union { uint32_t value; struct { uint32_t rxReqForceDeassertion : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 31; }; } DEBUG_PHY; // @ 0x55c }; diff --git a/src/include/phy/mac_pl.h b/src/include/phy/mac_pl.h index 3c9c7ad..918266a 100644 --- a/src/include/phy/mac_pl.h +++ b/src/include/phy/mac_pl.h @@ -7,6 +7,7 @@ typedef union { uint32_t value; struct { uint32_t nextTBTT : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } NEXT_TBTT; // @ 0x40 uint8_t pad1[0x4]; @@ -23,6 +24,7 @@ typedef union { uint32_t value; struct { uint32_t softReset : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 31; }; } MAC_CNTRL_2; // @ 0x50 uint8_t pad3[0x18]; @@ -55,6 +57,7 @@ typedef union { uint32_t phyRxStart : 1; // @ 23 -- 23 # 0xff7fffff uint32_t rxHeaderDMADead : 1; // @ 24 -- 24 # 0xfeffffff uint32_t rxPayloadDMADead : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t pad1 : 6; }; } GEN_INT_STATUS; // @ 0x6c union { @@ -85,6 +88,7 @@ typedef union { uint32_t phyRxStart : 1; // @ 23 -- 23 # 0xff7fffff uint32_t rxHeaderDMADead : 1; // @ 24 -- 24 # 0xfeffffff uint32_t rxPayloadDMADead : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t pad1 : 6; }; } GEN_INT_ACK; // @ 0x70 union { @@ -152,6 +156,7 @@ typedef union { uint32_t ac2TxBufTrigger : 1; // @ 26 -- 26 # 0xfbffffff uint32_t ac3TxBufTrigger : 1; // @ 27 -- 27 # 0xf7ffffff uint32_t bcnTxBufTrigger : 1; // @ 28 -- 28 # 0xefffffff + uint32_t pad0 : 3; }; } TX_RX_INT_STATUS; // @ 0x78 union { @@ -186,6 +191,7 @@ typedef union { uint32_t ac2TxBufTrigger : 1; // @ 26 -- 26 # 0xfbffffff uint32_t ac3TxBufTrigger : 1; // @ 27 -- 27 # 0xf7ffffff uint32_t bcnTxBufTrigger : 1; // @ 28 -- 28 # 0xefffffff + uint32_t pad1 : 3; }; } TX_RX_INT_ACK; // @ 0x7c union { @@ -237,6 +243,7 @@ typedef union { uint32_t absTimers7 : 1; // @ 7 -- 7 # 0xffffff7f uint32_t absTimers8 : 1; // @ 8 -- 8 # 0xfffffeff uint32_t absTimers9 : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t pad0 : 22; }; } TIMERS_INT_EVENT_SET; // @ 0x84 union { @@ -252,6 +259,7 @@ typedef union { uint32_t absTimers7 : 1; // @ 7 -- 7 # 0xffffff7f uint32_t absTimers8 : 1; // @ 8 -- 8 # 0xfffffeff uint32_t absTimers9 : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t pad0 : 22; }; } TIMERS_INT_EVENT_CLEAR; // @ 0x88 union { @@ -267,6 +275,7 @@ typedef union { uint32_t maskabsTimers7 : 1; // @ 7 -- 7 # 0xffffff7f uint32_t maskabsTimers8 : 1; // @ 8 -- 8 # 0xfffffeff uint32_t maskabsTimers9 : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t pad0 : 22; }; } TIMERS_INT_UN_MASK; // @ 0x8c uint8_t pad4[0x14]; @@ -299,6 +308,7 @@ typedef union { uint32_t value; struct { uint32_t ppduMCSIndex : 7; // @ 6 -- 0 # 0xffffff80 + uint32_t pad0 : 25; }; } TIME_ON_AIR_PARAM_2; // @ 0x164 union { @@ -336,6 +346,7 @@ typedef union { uint32_t rxPayloadNewTail : 1; // @ 25 -- 25 # 0xfdffffff uint32_t rxHeaderNewHead : 1; // @ 26 -- 26 # 0xfbffffff uint32_t rxPayloadNewHead : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t pad3 : 4; }; } DMA_CNTRL_SET; // @ 0x180 union { @@ -363,6 +374,7 @@ typedef union { uint32_t rxPayloadNewTail : 1; // @ 25 -- 25 # 0xfdffffff uint32_t rxHeaderNewHead : 1; // @ 26 -- 26 # 0xfbffffff uint32_t rxPayloadNewHead : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t pad3 : 4; }; } DMA_CNTRL_CLEAR; // @ 0x184 union { @@ -381,6 +393,7 @@ typedef union { uint32_t rxHeaderState : 2; // @ 25 -- 24 # 0xfcffffff uint32_t pad5 : 2; uint32_t rxPayloadState : 2; // @ 29 -- 28 # 0xcfffffff + uint32_t pad6 : 2; }; } DMA_STATUS_1; // @ 0x188 union { @@ -416,6 +429,7 @@ typedef union { uint32_t txAC1NewHeadErr : 1; // @ 27 -- 27 # 0xf7ffffff uint32_t txAC2NewHeadErr : 1; // @ 28 -- 28 # 0xefffffff uint32_t txAC3NewHeadErr : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t pad0 : 2; }; } DMA_STATUS_2; // @ 0x18c union { @@ -429,6 +443,7 @@ typedef union { uint32_t rxPayBusErr : 1; // @ 5 -- 5 # 0xffffffdf uint32_t rxHdrNewHeadErr : 1; // @ 6 -- 6 # 0xffffffbf uint32_t rxPayNewHeadErr : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t pad0 : 24; }; } DMA_STATUS_3; // @ 0x190 union { @@ -449,6 +464,7 @@ typedef union { uint32_t txAC1HaltAfterTXOP : 1; // @ 12 -- 12 # 0xffffefff uint32_t txAC2HaltAfterTXOP : 1; // @ 13 -- 13 # 0xffffdfff uint32_t txAC3HaltAfterTXOP : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t pad0 : 17; }; } DMA_STATUS_4; // @ 0x194 union { @@ -489,6 +505,7 @@ typedef union { uint32_t dmaTBDSize : 6; // @ 17 -- 12 # 0xfffc0fff uint32_t dmaRHDSize : 6; // @ 23 -- 18 # 0xff03ffff uint32_t dmaRBDSize : 6; // @ 29 -- 24 # 0xc0ffffff + uint32_t pad0 : 2; }; } TX_STRUCT_SIZES; // @ 0x1ac uint8_t pad7[0x8]; @@ -514,6 +531,7 @@ typedef union { uint32_t txFIFOThreshold : 8; // @ 7 -- 0 # 0xffffff00 uint32_t pad0 : 8; uint32_t rxFIFOThreshold : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t pad1 : 8; }; } DMA_THRESHOLD; // @ 0x1c0 uint8_t pad8[0x4c]; @@ -524,6 +542,7 @@ typedef union { uint32_t ac1HasData : 1; // @ 1 -- 1 # 0xfffffffd uint32_t ac2HasData : 1; // @ 2 -- 2 # 0xfffffffb uint32_t ac3HasData : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pad0 : 28; }; } EDCA_AC_HAS_DATA_SET; // @ 0x210 union { @@ -533,6 +552,7 @@ typedef union { uint32_t ac1HasData : 1; // @ 1 -- 1 # 0xfffffffd uint32_t ac2HasData : 1; // @ 2 -- 2 # 0xfffffffb uint32_t ac3HasData : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pad0 : 28; }; } EDCA_AC_HAS_DATA_CLEAR; // @ 0x214 uint8_t pad9[0x10]; @@ -562,6 +582,7 @@ typedef union { uint32_t value; struct { uint32_t txBWAfterDrop : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 30; }; } TX_BW_DROP_INFO; // @ 0x330 uint8_t pad11[0x30]; @@ -592,6 +613,7 @@ typedef union { uint32_t secU3ac1TxBufTrigger : 1; // @ 21 -- 21 # 0xffdfffff uint32_t secU3ac2TxBufTrigger : 1; // @ 22 -- 22 # 0xffbfffff uint32_t secU3ac3TxBufTrigger : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t pad0 : 8; }; } SEC_USERS_TX_INT_EVENT_SET; // @ 0x364 union { @@ -621,6 +643,7 @@ typedef union { uint32_t secU3ac1TxBufTrigger : 1; // @ 21 -- 21 # 0xffdfffff uint32_t secU3ac2TxBufTrigger : 1; // @ 22 -- 22 # 0xffbfffff uint32_t secU3ac3TxBufTrigger : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t pad0 : 8; }; } SEC_USERS_TX_INT_EVENT_CLEAR; // @ 0x368 union { diff --git a/src/include/phy/mdm.h b/src/include/phy/mdm.h index 341242e..1ab9362 100644 --- a/src/include/phy/mdm.h +++ b/src/include/phy/mdm.h @@ -36,6 +36,7 @@ typedef union { uint32_t CFGSMOOTHFORCE : 1; // @ 18 -- 18 # 0xfffbffff uint32_t SMOOTHEN : 1; // @ 19 -- 19 # 0xfff7ffff uint32_t TDCYCROTVAL80 : 8; // @ 27 -- 20 # 0xf00fffff + uint32_t pad0 : 4; }; } SMOOTHCTRL; // @ 0x818 union { @@ -44,6 +45,7 @@ typedef union { uint32_t WAITHTSTF : 7; // @ 6 -- 0 # 0xffffff80 uint32_t pad0 : 1; uint32_t delaynormalgi : 6; // @ 13 -- 8 # 0xffffc0ff + uint32_t pad1 : 18; }; } DCESTIMCTRL; // @ 0x81c union { @@ -63,6 +65,7 @@ typedef union { uint32_t rxmumimoapeplenen : 1; // @ 20 -- 20 # 0xffefffff uint32_t pad5 : 3; uint32_t rxcbwmax : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t pad6 : 6; }; } rxchan; // @ 0x820 union { @@ -80,6 +83,7 @@ typedef union { uint32_t ntxmax : 3; // @ 22 -- 20 # 0xff8fffff uint32_t pad5 : 1; uint32_t txcbwmax : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t pad6 : 6; }; } txchan; // @ 0x824 uint8_t pad2[0x8]; @@ -88,6 +92,7 @@ typedef union { struct { uint32_t smoothsnrthrmid : 8; // @ 7 -- 0 # 0xffffff00 uint32_t smoothsnrthrhigh : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t pad0 : 16; }; } SMOOTHSNRTHR; // @ 0x830 union { @@ -105,6 +110,7 @@ typedef union { uint32_t value; struct { uint32_t tbe_count_adjust_20 : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pad0 : 24; }; } TBECTRL0; // @ 0x858 uint8_t pad4[0x4]; @@ -117,6 +123,7 @@ typedef union { uint32_t rcclkforce : 1; // @ 27 -- 27 # 0xf7ffffff uint32_t pad1 : 1; uint32_t mdm_agcmemclkforce : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t pad2 : 2; }; } r0x874; // @ 0x874 uint8_t pad6[0x10]; @@ -130,6 +137,7 @@ typedef union { uint32_t DSPSWRESET : 1; // @ 8 -- 8 # 0xfffffeff uint32_t pad2 : 3; uint32_t AGCSWRESET : 1; // @ 12 -- 12 # 0xffffefff + uint32_t pad3 : 19; }; } swreset; // @ 0x888 uint32_t txctrl1; // @ 0x88c @@ -142,6 +150,7 @@ typedef union { struct { uint32_t pad0 : 16; uint32_t precomp : 6; // @ 21 -- 16 # 0xffc0ffff + uint32_t pad1 : 10; }; } r3024; // @ 0x3024 uint8_t pad9[0x8]; diff --git a/src/include/phy/sysctrl.h b/src/include/phy/sysctrl.h index 208b8c3..8f186ab 100644 --- a/src/include/phy/sysctrl.h +++ b/src/include/phy/sysctrl.h @@ -7,6 +7,7 @@ typedef union { uint32_t value; struct { uint32_t diag_sel : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; }; } diag_conf; // @ 0x68 uint8_t pad1[0x8]; @@ -16,6 +17,7 @@ typedef union { uint32_t value; struct { uint32_t time_greater_on_bit12 : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 31; }; } time; // @ 0x84 uint8_t pad3[0x58]; @@ -24,6 +26,7 @@ typedef union { struct { uint32_t pad0 : 8; uint32_t set1 : 9; // @ 16 -- 8 # 0xfffe00ff + uint32_t pad1 : 15; }; } misc_cntl; // @ 0xe0 }; From 5968b959875a645362707faf2185b8bc4ffd2944 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sat, 24 Jul 2021 04:41:26 -0500 Subject: [PATCH 033/148] put irqmacccatimeouten as field name --- script/manualext.py | 2 +- src/include/phy/agc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/script/manualext.py b/script/manualext.py index 6693cb3..d55faab 100755 --- a/script/manualext.py +++ b/script/manualext.py @@ -130,7 +130,7 @@ Reg('RWNXAGCCCATIMEOUT', 0x44c0b3bc) # 4000000 Reg('irqmacccatimeouten', 0x44c0b414) -Field('set1', 0xFFFFFEFF) +Field('irqmacccatimeouten', 0xFFFFFEFF) Reg('rwnxmacintstatmasked', 0x44c0b41c) FieldBit('needreset', 8) # guess diff --git a/src/include/phy/agc.h b/src/include/phy/agc.h index c89c8ad..1a2d832 100644 --- a/src/include/phy/agc.h +++ b/src/include/phy/agc.h @@ -185,7 +185,7 @@ typedef union { uint32_t value; struct { uint32_t pad0 : 8; - uint32_t set1 : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t irqmacccatimeouten : 1; // @ 8 -- 8 # 0xfffffeff uint32_t pad1 : 23; }; } irqmacccatimeouten; // @ 0x414 From bdac2397107d7597dc65d0ddcb4ea85e3cd16446 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sat, 24 Jul 2021 07:05:00 -0500 Subject: [PATCH 034/148] fix agc --- script/manualext.py | 8 +++++--- src/include/phy/agc.h | 14 +++++++------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/script/manualext.py b/script/manualext.py index d55faab..b23b600 100755 --- a/script/manualext.py +++ b/script/manualext.py @@ -118,7 +118,9 @@ Reg('RWNXAGCCNTL', 0x44c0b390) Field('combpathsel', 0xfffffffc) Field('agcfsmreset', 0xffffefff) # set 1 before agc mem, maybe -Field('rifsdeten', 0xfffffbff) +#Field('rifsdeten', 0xfffffbff) +#Field('riu_ofdmonly_setf', 0xfffffeff) + Reg('riu_rwnxagcaci20marg0', 0x44c0b340) Reg('riu_rwnxagcaci20marg1', 0x44c0b344) Reg('riu_rwnxagcaci20marg2', 0x44c0b348) @@ -256,7 +258,7 @@ def scan_write(code, dat="dat"): extra_regs = [ "rc_paoff_delay", - "riu_agcfsmreset", + "riu_ofdmonly", "riu_txshift4044", "riu_rxiqphaseesten", "riu_rxiqgainesten", @@ -274,7 +276,7 @@ def scan_write(code, dat="dat"): "write_volatile_4(DAT_44c0b110,uVar4 & 0xfffffffd);", "write_volatile_4(DAT_44c0b110,uVar4 & 0xfffffffe);", ]): - f.name = agc_attr[i][1] + f.name = extra_regs[i] i = i + 1 #open('../src/include/phy/agc.h', 'w').write('\n'.join(GenHeader())) #print('\n'.join(GenHeader())) diff --git a/src/include/phy/agc.h b/src/include/phy/agc.h index 1a2d832..267ce23 100644 --- a/src/include/phy/agc.h +++ b/src/include/phy/agc.h @@ -15,10 +15,10 @@ typedef union { union { uint32_t value; struct { - uint32_t riu_adcpowsupthrdbm : 1; // @ 0 -- 0 # 0xfffffffe - uint32_t riu_adcpowmindbm : 1; // @ 1 -- 1 # 0xfffffffd - uint32_t riu_vpeakadcqdbv : 1; // @ 2 -- 2 # 0xfffffffb - uint32_t riu_fe40gain : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t riu_rxiqgaincompen : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t riu_rxiqphasecompen : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t riu_rxiqgainesten : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t riu_rxiqphaseesten : 1; // @ 3 -- 3 # 0xfffffff7 uint32_t pad0 : 28; }; } r0xb110; // @ 0x110 @@ -120,7 +120,7 @@ typedef union { struct { uint32_t combpathsel : 2; // @ 1 -- 0 # 0xfffffffc uint32_t pad0 : 6; - uint32_t riu_rifsdeten : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t riu_ofdmonly : 1; // @ 8 -- 8 # 0xfffffeff uint32_t pad1 : 1; uint32_t riu_rifsdeten : 1; // @ 10 -- 10 # 0xfffffbff uint32_t pad2 : 1; @@ -204,7 +204,7 @@ typedef union { uint32_t value; struct { uint32_t pad0 : 12; - uint32_t riu_fe20gain : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t riu_txshift4044 : 2; // @ 13 -- 12 # 0xffffcfff uint32_t pad1 : 18; }; } r0xb500; // @ 0x500 @@ -213,7 +213,7 @@ typedef union { uint32_t value; struct { uint32_t pad0 : 16; - uint32_t riu_htstfgainen : 10; // @ 25 -- 16 # 0xfc00ffff + uint32_t rc_paoff_delay : 10; // @ 25 -- 16 # 0xfc00ffff uint32_t pad1 : 6; }; } r0xc020; // @ 0x1020 From 5ab3eca41430d5e3898c6370b9ef78cf8da08789 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sat, 24 Jul 2021 07:19:01 -0500 Subject: [PATCH 035/148] fix var names --- src/bl602_wifi/phy_bl602.c | 202 +++++++++++++++++++------------------ 1 file changed, 102 insertions(+), 100 deletions(-) diff --git a/src/bl602_wifi/phy_bl602.c b/src/bl602_wifi/phy_bl602.c index 7931908..3ed6880 100644 --- a/src/bl602_wifi/phy_bl602.c +++ b/src/bl602_wifi/phy_bl602.c @@ -58,84 +58,86 @@ void phy_get_version(uint32_t *version_1,uint32_t *version_2) { } void agc_config(void) { - AGC->RWNXAGCCNTL.set_0x0_0 = 0x0; - AGC->RWNXAGCCNTL.set_0x0_1 = 0x0; - AGC->r0xb3a4.set_0x0_2 = 0x0; - AGC->r0xb3a4.set_0x0_3 = 0x0; - AGC->r0xb394.set_0xf8_4 = 0xf8; - AGC->r0xb398.set_0x9e_5 = 0x9e; - AGC->r0xb3c4.set_0xce_6 = 0xce; - AGC->r0xb364.set_0x8_7 = 0x8; - AGC->r0xb364.set_0x3c_8 = 0x3c; - AGC->r0xb364.set_0x38_9 = 0x38; - AGC->r0xb364.set_0x39_10 = 0x39; - AGC->r0xb368.set_0x70_11 = 0x70; - AGC->r0xb368.set_0x70_12 = 0x70; - AGC->r0xb36c.set_0x12_13 = 0x12; - AGC->r0xb36c.set_0x5_14 = 0x5; - AGC->r0xb36c.set_0x28_15 = 0x28; - AGC->r0xb36c.set_0x7_16 = 0x7; - AGC->r0xb370.set_0x58_17 = 0x58; - AGC->r0xb3c0.set_0x18_18 = 0x18; - AGC->r0xb380.set_0x3e_19 = 0x3e; - AGC->r0xb380.set_0x37_20 = 0x37; - AGC->r0xb380.set_0x1_21 = 0x1; - AGC->r0xb380.set_0x0_22 = 0x0; - AGC->r0xb380.set_0x1_23 = 0x1; - AGC->r0xb384.set_0x39_24 = 0x39; - AGC->r0xb384.set_0x37_25 = 0x37; - AGC->r0xb384.set_0x14_26 = 0x14; - AGC->r0xb384.set_0x0_27 = 0x0; - AGC->r0xb384.set_0x2_28 = 0x2; - AGC->r0xb388.set_0xf_29 = 0xf; - AGC->r0xb388.set_0x17_30 = 0x17; - AGC->r0xb388.set_0x2a_31 = 0x2a; - AGC->r0xb388.set_0x0_32 = 0x0; - AGC->r0xb388.set_0x5_33 = 0x5; - AGC->r0xb38c.set_0x19_34 = 0x19; - AGC->r0xb38c.set_0x0_35 = 0x0; - AGC->r0xb38c.set_0xe_36 = 0xe; - AGC->r0xb38c.set_0x2_37 = 0x2; - AGC->r0xc830.set_0x3f_38 = 0x3f; - AGC->r0xc830.set_0x1_39 = 0x1; - AGC->r0xc830.set_0x36_40 = 0x36; - AGC->r0xc830.set_0x5_41 = 0x5; - AGC->r0xc814.set_0x0_42 = 0x0; - AGC->r0xc040.set_0xc_43 = 0xc; - AGC->r0xc040.set_0x3_44 = 0x3; - AGC->r0xc044.set_0x8_45 = 0x8; - AGC->r0xc044.set_0x0_46 = 0x0; + AGC->RWNXAGCCNTL.riu_htstfgainen = 0x0; + AGC->RWNXAGCCNTL.riu_rifsdeten = 0x0; + AGC->r0xb3a4.riu_fe20gain = 0x0; + AGC->r0xb3a4.riu_fe40gain = 0x0; + AGC->r0xb394.riu_vpeakadcqdbv = 0xf8; + AGC->r0xb398.riu_adcpowmindbm = 0x9e; + AGC->r0xb3c4.riu_adcpowsupthrdbm = 0xce; + AGC->r0xb364.riu_satdelay50ns = 0x8; + AGC->r0xb364.riu_sathighthrdbv = 0x3c; + AGC->r0xb364.riu_satlowthrdbv = 0x38; + AGC->r0xb364.riu_satthrdbv = 0x39; + AGC->r0xb368.riu_crossdnthrqdbm = 0x70; + AGC->r0xb368.riu_crossupthrqdbm = 0x70; + AGC->RWNXAGCRAMP.riu_rampupgapqdb = 0x12; + AGC->RWNXAGCRAMP.riu_rampupndlindex = 0x5; + AGC->RWNXAGCRAMP.riu_rampdngapqdb = 0x28; + AGC->RWNXAGCRAMP.riu_rampdnndlindex = 0x7; + AGC->r0xb370.riu_adcpowdisthrdbv = 0x58; + AGC->r0xb3c0.riu_idinbdpowgapdnqdbm = 0x18; + AGC->r0xb380.riu_evt0op3 = 0x3e; + AGC->r0xb380.riu_evt0op2 = 0x37; + AGC->r0xb380.riu_evt0op1 = 0x1; + AGC->r0xb380.riu_evt0pathcomb = 0x0; + AGC->r0xb380.riu_evt0opcomb = 0x1; + AGC->r0xb384.riu_evt1op1 = 0x39; + AGC->r0xb384.riu_evt1op2 = 0x37; + AGC->r0xb384.riu_evt1op3 = 0x14; + AGC->r0xb384.riu_evt1pathcomb = 0x0; + AGC->r0xb384.riu_evt1opcomb = 0x2; + AGC->r0xb388.riu_evt2op1 = 0xf; + AGC->r0xb388.riu_evt2op2 = 0x17; + AGC->r0xb388.riu_evt2op3 = 0x2a; + AGC->r0xb388.riu_evt2pathcomb = 0x0; + AGC->r0xb388.riu_evt2opcomb = 0x5; + AGC->r0xb38c.riu_evt3op1 = 0x19; + AGC->r0xb38c.riu_evt3op2 = 0x0; + AGC->r0xb38c.riu_evt3op3 = 0xe; + AGC->r0xb38c.riu_evt3opcomb = 0x2; + AGC->r0xc830.rc2_evt4op1 = 0x3f; + AGC->r0xc830.rc2_evt4op2 = 0x1; + AGC->r0xc830.rc2_evt4op3 = 0x36; + AGC->r0xc830.rc2_evt4opcomb = 0x5; + AGC->r0xc814.rc2_pkdet_mode = 0x0; + AGC->r0xc814.rc2_pkdet_cnt_thr = 0x2; + AGC->r0xc814.rc2_pkdet_cnt_thr = 0x2; + AGC->r0xc040.rc2_rx0_vga_idx_max = 0xc; + AGC->r0xc040.rc2_rx0_vga_idx_min = 0x3; + AGC->r0xc044.rc2_rx0_lna_idx_max = 0x8; + AGC->r0xc044.rc2_rx0_lna_idx_min = 0x0; phy_config_rxgain(0); - AGC->r0xb3a0.set_0x9e_47 = 0x9e; - AGC->r0xb3c0.set_0xa4_48 = 0xa4; - AGC->r0xb3c0.set_0xa3_49 = 0xa3; - AGC->r0xc82c.set_0xb5_50 = 0xb5; - AGC->r0xc82c.set_0x1_51 = 0x1; - AGC->r0xc82c.set_0x1_52 = 0x1; - AGC->r0xc838.set_0x1_53 = 0x1; - AGC->r0xc838.set_0x100_54 = 0x100; - AGC->r0xc83c.set_0x1_55 = 0x1; - AGC->r0xc83c.set_0x17c_56 = 0x17c; - AGC->r0xc840.set_0x1_57 = 0x1; - AGC->r0xc840.set_0x100_58 = 0x100; - AGC->r0xc82c.set_0x40_59 = 0x40; + AGC->r0xb3a0.riu_inbdpowmindbm = 0x9e; + AGC->r0xb3c0.riu_inbdpowsupthrdbm = 0xa4; + AGC->r0xb3c0.riu_inbdpowinfthrdbm = 0xa3; + AGC->r0xc82c.rc2_inbdpow_adj_thr_dbm = 0xb5; + AGC->r0xc82c.rc2_inbdpowsupthr_adj_en = 0x1; + AGC->r0xc82c.rc2_inbdpowinfthr_adj_en = 0x1; + AGC->r0xc838.rc2_reflevofdmthd_en = 0x1; + AGC->r0xc838.rc2_reflevofdmthd = 0x100; + AGC->r0xc83c.rc2_reflevdsssthd_en = 0x1; + AGC->r0xc83c.rc2_reflevdsssthd = 0x17c; + AGC->r0xc840.rc2_reflevdssscontthd_en = 0x1; + AGC->r0xc840.rc2_reflevdssscontthd = 0x100; + AGC->r0xc82c.rc2_inbdpowfastvalid_cnt = 0x40; } void bz_phy_reset(void) { - BZ_PHY->r0x2808.set_0x1_67 = 0x1; - BZ_PHY->r0x2808.set_0x8_68 = 0x8; - BZ_PHY->r0x280c.set_0x1_69 = 0x1; - BZ_PHY->r0x280c.set_0x4_70 = 0x4; - BZ_PHY->r0x280c.set_0x0_71 = 0x0; - BZ_PHY->r0x2854.set_0x20_72 = 0x20; - BZ_PHY->r0x2854.set_0x1e_73 = 0x1e; - BZ_PHY->r0x2854.set_0xa_74 = 0xa; - BZ_PHY->r0x2854.set_0x1e_75 = 0x1e; - BZ_PHY->r0x2810.set_0x0_76 = 0x0; - BZ_PHY->r0x2810.set_0x1_77 = 0x1; - BZ_PHY->r0x2cac.set_0x4_78 = 0x4; + BZ_PHY->r0x2808.bz_phy_tx_rampup_fm_on = 0x1; + BZ_PHY->r0x2808.bz_phy_tx_rampup_time_us = 0x8; + BZ_PHY->r0x280c.bz_phy_tx_rampdn_fm_on = 0x1; + BZ_PHY->r0x280c.bz_phy_tx_rampdn_time_us = 0x4; + BZ_PHY->r0x280c.bz_phy_tx_rampdn_pad0_time_us = 0x0; + BZ_PHY->r0x2854.bz_phy_rx_proc_time_mlsd_us = 0x20; + BZ_PHY->r0x2854.bz_phy_rx_proc_time_direct_us = 0x1e; + BZ_PHY->r0x2854.bz_phy_rx_proc_time_eq_us = 0xa; + BZ_PHY->r0x2854.bz_phy_rx_proc_time_viterbi_us = 0x1e; + BZ_PHY->r0x2810.bz_phy_rx_dfe_notch_en = 0x0; + BZ_PHY->r0x2810.bz_phy_rx_dfe_toc_en = 0x1; + BZ_PHY->r0x2cac.bz_agc_rbb_ind_min = 0x4; return ; } @@ -193,17 +195,17 @@ int phy_freq_to_channel(uint8_t band, uint16_t freq); void phy_hw_set_channel(uint8_t band, uint16_t freq, uint16_t freq1, uint8_t chantype) { ASSERT_ERR(chantype == PHY_CHNL_BW_20); ASSERT_ERR(band == PHY_BAND_2G4); - AGC->RWNXAGCCNTL.set_0x0_61 = 0; - MDM->rxchan.reset = 1; + AGC->RWNXAGCCNTL.riu_ofdmonly = 0; + MDM->rxchan.rxdsssen = 1; MDM->mdmconf = 0; mdm_reset(); - MDM->TXCTRL0 = 0xb4; - MDM->TXCTRL1 = 0x1c13; - MDM->TXCTRL3 = 0x2d00438; + MDM->txstartdelay = 0xb4; + MDM->txctrl1 = 0x1c13; + MDM->txctrl3 = 0x2d00438; MDM->TBECTRL0.tbe_count_adjust_20 = 0; MDM->DCESTIMCTRL.value = 0xf0f; MDM->DCESTIMCTRL.WAITHTSTF = 7; - MDM->r834.set60h = 0x6; + MDM->r834.tddchtstfmargin = 0x6; MDM->SMOOTHCTRL.value = 0x1880c06; MDM->tbectrl2 = 0x7f03; AGC->riu_rwnxagcaci20marg0 = 0; @@ -256,51 +258,51 @@ void phy_init(phy_cfg_tag *config) { mdm_reset(); MDM->rxchan.value = 0x20d; MDM->rxchan.rxnssmax = phy_get_nss(); - MDM->rxchan.rxndpnstsmax = MDM->version.rxndpnstsmax; - MDM->rxchan.v19 = MDM->version.v19; - MDM->rxchan.vht = phy_vht_supported(); - MDM->rxchan.v30 = MDM->version.mu_mimo_rx; + MDM->rxchan.rxndpnstsmax = MDM->version.nsts; + MDM->rxchan.rxldpcen = MDM->version.ldpcdec; + MDM->rxchan.rxvhten = phy_vht_supported(); + MDM->rxchan.rxmumimoen = MDM->version.mu_mimo_rx; MDM->r3024.precomp = 0x2D; MDM->rxframeviolationmask = 0xffffffff; MDM->txchan.value = 0x20d; MDM->txchan.txnssmax = phy_get_nss(); MDM->txchan.ntxmax = phy_get_ntx(); - MDM->txchan.txcbwmax = MDM->version.txcbwmax; - MDM->txchan.v18 = MDM->version.v18; + MDM->txchan.txcbwmax = MDM->version.chbw; + MDM->txchan.txldpcen = MDM->version.ldpcenc; MDM->txchan.vht = phy_vht_supported(); - MDM->txchan.v31 = MDM->version.mu_mimo_tx; + MDM->txchan.txmumimoen = MDM->version.mu_mimo_tx; - MDM->r834.set1 = 1; + MDM->r834.rxtdctrl1 = 1; MDM->SMOOTHCTRL.CFGSMOOTHFORCE = 0; MDM->SMOOTHSNRTHR.smoothsnrthrhigh = 0x1b; MDM->SMOOTHSNRTHR.smoothsnrthrmid = 0xf; MDM->rxctrl1 = 0x4920492; - MDM->r874.resetto1 = 1; + MDM->r0x874.rcclkforce = 1; - AGC->r0xb500.set_0x2_62 = 0x02; + AGC->r0xb500.riu_txshift4044 = 0x02; if (AGC->r000.iqcomp) { - AGC->r0xb110.set_0x0_63 = 0; - AGC->r0xb110.set_0x0_64 = 0; - AGC->r0xb110.set_0x0_65 = 0; - AGC->r0xb110.set_0x0_66 = 0; + AGC->r0xb110.riu_rxiqphaseesten = 0; + AGC->r0xb110.riu_rxiqgainesten = 0; + AGC->r0xb110.riu_rxiqphasecompen = 0; + AGC->r0xb110.riu_rxiqgaincompen = 0; AGC->riu_iqestiterclr = 0; } AGC->activeant = 1; - AGC->RWNXAGCCNTL.set1 = 1; + AGC->RWNXAGCCNTL.combpathsel = 1; AGC->RWNXAGCCCATIMEOUT = 4000000; - AGC->irqmacccatimeouten.set1 = 1; + AGC->irqmacccatimeouten.irqmacccatimeouten = 1; agc_config(); AGC->RWNXAGCCNTL.agcfsmreset = 1; - MDM->r874.set1beforewriteagcmem = 1; + MDM->r0x874.mdm_agcmemclkforce = 1; for (int i = 0; i < 0x200; i++) AGCRAM->agcram[i] = agcmem[i]; - MDM->r874.set1beforewriteagcmem = 0; + MDM->r0x874.mdm_agcmemclkforce = 0; AGC->RWNXAGCCNTL.agcfsmreset = 0; - AGC->r0xc020.set_0x14_60 = 0x14; + AGC->r0xc020.rc_paoff_delay = 0x14; phy_env[0].cfg.reserved = (config->parameters)[0]; phy_env[0].chnl_center1_freq = 0xff; phy_env[0].chnl_center2_freq = 0xff; @@ -316,7 +318,7 @@ void phy_init(phy_cfg_tag *config) { uint8_t phy_vht_supported(){ if (MDM->version.vht) // TODO: verify this cond return 1; - return ((MDM->version.txcbwmax) >> 1) & 1; + return ((MDM->version.chbw) >> 1) & 1; } uint8_t phy_ldpc_rx_supported(void){ @@ -340,8 +342,8 @@ uint8_t phy_mu_mimo_tx_supported(void) { } void phy_rc_isr(void) { - uint32_t val = AGC->r41c.value; - AGC->r420_copy41c = val; + uint32_t val = AGC->rwnxmacintstatmasked.value; + AGC->rwnxmacintack = val; if (val & 0x100) { mdm_reset(); } From c158eeaf86485d7e89150b4db2b13422a07397da Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sat, 24 Jul 2021 21:34:31 -0500 Subject: [PATCH 036/148] fix regs and add phy_adapt --- script/manualext.py | 10 ++- src/bl602_wifi/assert.h | 6 ++ src/bl602_wifi/hal_desc.h | 121 +++++++++++++++++++++++++ src/bl602_wifi/phy_adapt.c | 175 +++++++++++++++++++++++++++++++++++++ src/bl602_wifi/phy_adapt.h | 92 ++++++++++++++++++- src/bl602_wifi/phy_bl602.c | 36 ++------ src/bl602_wifi/phy_bl602.h | 76 +++++++++++++++- src/bl602_wifi/phy_hal.h | 17 ++++ src/bl602_wifi/utils.h | 3 + src/include/stdint.h | 4 +- 10 files changed, 502 insertions(+), 38 deletions(-) create mode 100644 src/bl602_wifi/assert.h create mode 100644 src/bl602_wifi/hal_desc.h create mode 100644 src/bl602_wifi/phy_adapt.c create mode 100644 src/bl602_wifi/phy_hal.h create mode 100644 src/bl602_wifi/utils.h diff --git a/script/manualext.py b/script/manualext.py index b23b600..6304b8e 100755 --- a/script/manualext.py +++ b/script/manualext.py @@ -180,7 +180,7 @@ def scan_write(code, dat="dat"): name_r = f'r{hex(addr&0xffff)}' gid = gid + 1 r = Reg(name_r, addr) - yield r, Field(name_f, mask) + yield r, Field(name_f, mask), value agc_attr = [ @@ -249,12 +249,13 @@ def scan_write(code, dat="dat"): ] i = 0 -for r, f in scan_write(open('../blobs/agc_config.c').readlines()): +for r, f, val in scan_write(open('../blobs/agc_config.c').readlines()): if r.offset == agc_attr[i][0] - 0x44c0b000: f.name = agc_attr[i][1] else: print(f"mismatched {i} {agc_attr[i][1]} {hex(r.offset + 0x44c0b000)} {hex(agc_attr[i][0])}") i = i + 1 + #print(f"AGC->{r.name}.{f.name} = {hex(val)};") extra_regs = [ "rc_paoff_delay", @@ -267,7 +268,7 @@ def scan_write(code, dat="dat"): ] i = 0 -for _, f in scan_write([ +for _, f, _ in scan_write([ "write_volatile_4(DAT_44c0c020,uVar4 & 0xfc00ffff | 0x140000);", "write_volatile_4(DAT_44c0b390,uVar1 & 0xfffffeff);", "write_volatile_4(DAT_44c0b500,uVar4 & 0xffffcfff | 0x2000);", @@ -448,12 +449,13 @@ def getregs(fname, pattern='name'): ] i = 0 -for r, f in scan_write(open('../blobs/bz_phy.c').readlines(), '0x'): +for r, f, val in scan_write(open('../blobs/bz_phy.c').readlines(), '0x'): if r.offset == extra_bz_phy[i][0] - 0x40002000: f.name = extra_bz_phy[i][1] else: print(f"mismatched {i} {extra_bz_phy[i][1]} {hex(r.offset + 0x40002000)} {hex(extra_bz_phy[i][0])}") i = i + 1 + # print(f"BZ_PHY->{r.name}.{f.name} = {hex(val)}") if __name__ == '__main__': import sys diff --git a/src/bl602_wifi/assert.h b/src/bl602_wifi/assert.h new file mode 100644 index 0000000..0daa8c9 --- /dev/null +++ b/src/bl602_wifi/assert.h @@ -0,0 +1,6 @@ +#ifndef _ASSERT_H_ +#define _ASSERT_H_ +void assert_err(char * condition, char * file, int line); + +#define ASSERT_ERR(cond) if (!(cond)) assert_err(#cond, __FILE__, __LINE__); +#endif \ No newline at end of file diff --git a/src/bl602_wifi/hal_desc.h b/src/bl602_wifi/hal_desc.h new file mode 100644 index 0000000..6a68565 --- /dev/null +++ b/src/bl602_wifi/hal_desc.h @@ -0,0 +1,121 @@ + +#ifndef _HAL_DESC_H_ +#define _HAL_DESC_H_ +#include +struct tx_policy_tbl { + uint32_t upatterntx; // +0 + uint32_t phycntrlinfo1; // +4 + uint32_t phycntrlinfo2; // +8 + uint32_t maccntrlinfo1; // +12 + uint32_t maccntrlinfo2; // +16 + uint32_t ratecntrlinfo[4]; // +20 + uint32_t powercntrlinfo[4]; // +36 +}; // :669:8 + +struct tx_compressed_policy_tbl { + uint32_t upatterntx; // +0 + uint32_t sec_user_control; // +4 +}; // :689:8 + +struct tx_hd { + uint32_t upatterntx; // +0 + uint32_t nextfrmexseq_ptr; // +4 + uint32_t nextmpdudesc_ptr; // +8 + union { + uint32_t first_pbd_ptr; + uint32_t sec_user1_ptr; + }; // +12 + union { + uint32_t datastartptr; + uint32_t sec_user2_ptr; + }; // +16 + union { + uint32_t dataendptr; + uint32_t sec_user3_ptr; + }; // +20 + uint32_t frmlen; // +24 + uint32_t frmlifetime; // +28 + uint32_t phyctrlinfo; // +32 + uint32_t policyentryaddr; // +36 + uint32_t optlen[3]; // +40 + uint32_t macctrlinfo1; // +52 + uint32_t macctrlinfo2; // +56 + uint32_t statinfo; // +60 + uint32_t mediumtimeused; // +64 +}; // :698:8 + +struct tx_pbd { + uint32_t upatterntx; // +0 + uint32_t next; // +4 + uint32_t datastartptr; // +8 + uint32_t dataendptr; // +12 + uint32_t bufctrlinfo; // +16 +}; // :748:8 + +struct rx_hd { + uint32_t upatternrx; // +0 + uint32_t next; // +4 + uint32_t first_pbd_ptr; // +8 + struct rx_swdesc *swdesc; // +12 + uint32_t datastartptr; // +16 + uint32_t dataendptr; // +20 + uint32_t headerctrlinfo; // +24 + uint16_t frmlen; // +28 + uint16_t ampdu_stat_info; // +30 + uint32_t tsflo; // +32 + uint32_t tsfhi; // +36 + uint32_t recvec1a; // +40 + uint32_t recvec1b; // +44 + uint32_t recvec1c; // +48 + uint32_t recvec1d; // +52 + uint32_t recvec2a; // +56 + uint32_t recvec2b; // +60 + uint32_t statinfo; // +64 +}; // :774:8 + +struct rx_pbd { + uint32_t upattern; // +0 + uint32_t next; // +4 + uint32_t datastartptr; // +8 + uint32_t dataendptr; // +12 + uint16_t bufstatinfo; // +16 + uint16_t reserved; // +18 +}; // :816:8 + +struct rx_dmadesc { + struct rx_hd hd; // +0 + struct phy_channel_info phy_info; // +68 + uint32_t flags; // +76 + uint32_t pattern; // +80 + uint32_t payl_offset; // +84 + uint32_t reserved_pad[2]; // +88 + uint32_t use_in_tcpip; // +96 +}; // :834:8 + +struct rx_payloaddesc { + struct rx_pbd pbd; // +0 + uint32_t pd_status; // +20 + uint32_t *buffer_rx; // +24 + void *pbuf_holder[6]; // +28 +}; // :854:8 + +struct tx_cfm_tag { + uint16_t pn[4]; // +0 + uint16_t sn; // +8 + uint16_t timestamp; // +10 + int8_t credits; // +12 + uint8_t ampdu_size; // +13 + uint8_t pad[2]; // +14 + uint32_t status; // +16 +}; // :865:8 + +struct tx_hw_desc { + struct tx_cfm_tag *cfm_ptr; // +0 + struct tx_hd thd; // +4 +}; // :885:8 + +struct tx_agg_desc { + uint8_t reserved; // +0 +}; // :979:8 + +#endif \ No newline at end of file diff --git a/src/bl602_wifi/phy_adapt.c b/src/bl602_wifi/phy_adapt.c new file mode 100644 index 0000000..3f5d671 --- /dev/null +++ b/src/bl602_wifi/phy_adapt.c @@ -0,0 +1,175 @@ +#include "phy_adapt.h" +#include "utils.h" +#include "phy_hal.h" +#include "assert.h" + +static pa_state_t pa_env[4]; // :136:19 + +void pa_adapt(uint8_t id) { + static uint32_t count = 0; + count++; + if (id > 3) { + return ; + } + int next_ptr = pa_env[id].input_buffer_ptr; + int ptr = (next_ptr - 1 + 8) % 8; // (next_ptr - 1) & 7 + if (pa_env[id].input_buffer[ptr].new) { + int rssi = pa_env[id].input_buffer[ptr].rssi; + if (pa_env[id].rss_state == 0) { + if (pa_env[id].rss_count < 7) { + pa_env[id].rss_count ++; + } else { + pa_env[id].rss_state = 1; + int sum_rssi = 0; + int min_rssi = 100; + int max_rssi = -100; + for (int i = 1; i < 7; i++) { + int _rssi = (int)pa_env[id].input_buffer[(next_ptr - i) % 8].rssi; + sum_rssi = _rssi; + if (_rssi > max_rssi) { + max_rssi = _rssi; + } + if (_rssi < min_rssi) { + min_rssi = _rssi; + } + } + pa_env[id].rss = (sum_rssi - min_rssi - max_rssi) / 4; + } + } else { + if (pa_env[id].rss_hit_count < 5) { + if (rssi + 100 < 101) { + char rss = pa_env[id].rss; + int diff = rssi - rss; + if (diff + 10 < 21) { + pa_env[id].rss_hit_count = 0; + pa_env[id].rss = (char)(diff >> 2) + rss; + } else { + pa_env[id].rss_hit_count ++; + } + } + } else { + pa_env[id].rss_hit_count = 0; + pa_env[id].rss_state = 0; + pa_env[id].rss_count = 0; + } + } + + if ((count & 0xf) == 0xf) { + float ppm; + if ((rssi - pa_env[id].rss) + 10U < 0x15) { + ppm = pa_env[id].input_buffer[ptr].ppm; + if (ABS(ppm) < 2.0) { + double d_ppm = (double)ppm; + double a = 0; + double d_ce = ((double)pa_env[id].ce); + if (rssi < -0x55) { + d_ppm = d_ce * (double)0.03125; + // 0x3fa00000 00000000 + } else { + d_ppm = d_ce * (double)0.125; + // 0x3fc00000 00000000 + } + d_ppm += d_ce; + ppm = (float) d_ppm; + pa_env[id].ce = ppm; + } + } + ppm = pa_env[id].ce; + if (ABS(ppm) > 5) { + if (ppm > 0) { + int cap = hal_get_capcode(); + if (cap != 0) { + hal_set_capcode(hal_get_capcode() - 1); + } + } + if (ppm < 0) { + int cap = hal_get_capcode(); + if (cap < 0x3f) { + hal_set_capcode(hal_get_capcode() + 1); + } + } + pa_env[id].ce = 0.0; + } + } + } +} + +void pa_init(void) { + for (int i = 0; i < 3; i++) { + pa_env[i].rss_state = 0; + pa_env[i].rss_count = 0; + pa_env[i].rss_state = 0; + pa_env[i].rss_count = 0; + pa_env[i].last_update = 0; + pa_env[i].input_buffer_ptr = 0; + pa_env[i].ce_state = 0; + pa_env[i].ce = 0.0; + pa_env[i].ce_num_up_cmds = 0; + pa_env[i].ce_num_dn_cmds = 0; + for (int j = 0; j < 8; j++) { + pa_env[i].input_buffer[j].lna = 0; + pa_env[i].input_buffer[j].new = 0; + pa_env[i].input_buffer[j].ppm = 0; + pa_env[i].input_buffer[j].rssi = 0; + } + } +} + + +float calc_ppm_dsss(uint8_t rxv_freqoff) { + return ((double)rxv_freqoff) * 0.7; +} + +float calc_ppm_ofdm(uint16_t rxv_freqoff) { + return (((double)(-(int)rxv_freqoff)) * 20.0) / 2440.0; +} + +float calc_ppm(rvec_t * rvec) { + if ((rvec->format_mod) == 0 && (rvec->leg_rate < 4)) { + return calc_ppm_dsss(rvec->freqoff_lo); + } else { + return calc_ppm_ofdm(rvec->freqoff); + } +} + + +void pa_input(uint8_t id, struct rx_hd *rhd) { + if (id < 4) { + int ptr = pa_env[id].input_buffer_ptr; + rvec_t *rvec = &(rhd->recvec1a); + input_t *buffer = &(pa_env[id].input_buffer[ptr]); + pa_env[id].last_update = rhd->tsflo; + buffer->new = 1; + //pa_env[id].input_buffer[id].rssi = *(int8_t *)((int)&rhd->recvec1c + 3); + buffer->rssi = rvec->rssi1; + //pa_env[id].input_buffer[id].lna = (char)((int)(rhd->recvec1d << 20) >> 28); + buffer->lna = rvec->agc_lna; + buffer->ppm = calc_ppm(rvec); + ptr = (ptr + 1) & 7; + pa_env[id].input_buffer_ptr = ptr; + } +} + +int8_t pa_alloc(uint32_t vif_addr) { + for (int i = 0; i < 4; i++) { + if (!pa_env[i].used) { + pa_env[i].used = 1; + pa_env[i].vif_tag = vif_addr; + return i; + } + } + + return -1; +} + +void pa_reset(uint8_t id) { + return ; +} + +void pa_free(uint8_t id) { + if (id < 4) { + pa_env[id].used = 0; + pa_env[id].vif_tag = 0; + } +} + diff --git a/src/bl602_wifi/phy_adapt.h b/src/bl602_wifi/phy_adapt.h index 4de482b..7fbe645 100644 --- a/src/bl602_wifi/phy_adapt.h +++ b/src/bl602_wifi/phy_adapt.h @@ -1,6 +1,94 @@ #ifndef _PHY_ADAPT_H_ #define _PHY_ADAPT_H_ -void pa_adapt(void); +#include +#include "hal_desc.h" + +typedef struct { + int8_t rssi; // +0 + int8_t lna; // +1 + float ppm; // +4 + uint8_t new; // +8 +} input_t; // :53:3 + +typedef struct { + uint8_t used; // +0 + uint32_t vif_tag; // +4 + input_t input_buffer[8]; // +8 + int8_t input_buffer_ptr; // +104 + // input_buffer is something like a ring buffer + // input_buffer[input_buffer_ptr] is the in-coming data buffer + // and input_buffer[input_buffer_ptr -1, -2, -3, ..., -6] + // are available datas + // the most recent one is input_buffer[input_buffer_ptr -1] + // wrapped by math mod + uint32_t last_update; // +108 + int8_t rss; // +112 + int8_t rss_acq; // +113 + int8_t rss_trk; // +114 + int8_t rss_state; // +115 + uint8_t rss_hit_count; // +116 + uint32_t rss_count; // +120 + int8_t ris; // +124 + float ce; // +128 + int8_t ce_in; // +132 + int8_t ce_acq; // +133 + int8_t ce_trk; // +134 + int8_t ce_state; // +135 + int8_t ce_num_up_cmds; // +136 + int8_t ce_num_dn_cmds; // +137 +} pa_state_t; // :83:3 + +typedef struct { + uint32_t leg_length:12; // +0 + uint32_t leg_rate:4; // +0 + uint32_t ht_length:16; // +0 + + uint32_t _ht_length:4; // +4 + uint32_t short_gi:1; // +4 + uint32_t stbc:2; // +4 + uint32_t smoothing:1; // +4 + uint32_t mcs:7; // +4 + uint32_t pre_type:1; // +4 + uint32_t format_mod:3; // +4 + uint32_t ch_bw:2; // +4 + uint32_t n_sts:3; // +4 + uint32_t lsig_valid:1; // +4 + uint32_t sounding:1; // +4 + uint32_t num_extn_ss:2; // +4 + uint32_t aggregation:1; // +4 + uint32_t fec_coding:1; // +4 + uint32_t dyn_bw:1; // +4 + uint32_t doze_not_allowed:1; // +4 + + uint32_t antenna_set:8; // +8 + uint32_t partial_aid:9; // +8 + uint32_t group_id:6; // +8 + uint32_t reserved_1c:1; // +8 + int32_t rssi1:8; // +8 + int32_t rssi2:8; // +12 + int32_t agc_lna:4; // +12 + int32_t agc_rbb1:5; // +12 + int32_t agc_dg:7; // +12 + uint32_t reserved_1d:8; // +12 + uint32_t rcpi:8; // +16 + uint32_t evm1:8; // +16 + uint32_t evm2:8; // +16 + union { + uint32_t freqoff:16; + struct { + uint32_t freqoff_lo:8; // +16 + uint32_t freqoff_hi:8; // +20 + }; + }; + uint32_t reserved2b_1:8; // +20 + uint32_t reserved2b_2:8; // +20 + uint32_t reserved2b_3:8; // +20 +} rvec_t; // :134:3 + +void pa_adapt(uint8_t id); void pa_init(void); -void pa_input(void); +void pa_input(uint8_t id, struct rx_hd *rhd); +int8_t pa_alloc(uint32_t vif_addr); +void pa_reset(uint8_t id); +void pa_free(uint8_t id); #endif \ No newline at end of file diff --git a/src/bl602_wifi/phy_bl602.c b/src/bl602_wifi/phy_bl602.c index 3ed6880..4d98ce9 100644 --- a/src/bl602_wifi/phy_bl602.c +++ b/src/bl602_wifi/phy_bl602.c @@ -10,14 +10,7 @@ #include "phy_adapt.h" #include "phy_tcal.h" #include "rf.h" - -void assert_err(char * condition, char * file, int line); - -#define ASSERT_ERR(cond) if (!(cond)) assert_err(#cond, __FILE__, __LINE__); - -#define PHY_FORMATMOD_11B 0 -#define PHY_FORMATMOD_11G 1 -#define PHY_FORMATMOD_11N 2 +#include "assert.h" static int8_t rxgain_offset_vs_temperature; // :79:15 static int8_t poweroffset[14]; // :80:15 @@ -168,11 +161,11 @@ void phy_get_rf_gain_idx(int8_t *power,uint8_t *idx) { *idx = (uint8_t)rfc_get_power_level(2, (int)*power * 10); } -void phy_get_rf_gain_idx_vs_mode(uint8_t mode,int8_t *power,uint8_t *idx){ +void phy_get_rf_gain_idx_vs_mode(uint8_t mode,int8_t *power,uint8_t *idx) { *idx = (uint8_t)rfc_get_power_level(mode, (int)*power * 10); } -void phy_get_trpc_idx(uint8_t formatmod,uint8_t mcs,int8_t power,uint8_t *idx) { +void phy_get_trpc_idx(uint8_t formatmod,uint8_t mcs,int8_t power,uint8_t *idx) { // THIS IS ONLY MY GUESS. THE REAL DISASSEMBLY LOOKS VERY WEIRD AND IT MUST BE WRONG ASSERT_ERR(formatmod <= PHY_FORMATMOD_11N); if (formatmod == PHY_FORMATMOD_11G) @@ -190,8 +183,6 @@ void phy_powroffset_set(int8_t *power_offset) { } } -int phy_freq_to_channel(uint8_t band, uint16_t freq); - void phy_hw_set_channel(uint8_t band, uint16_t freq, uint16_t freq1, uint8_t chantype) { ASSERT_ERR(chantype == PHY_CHNL_BW_20); ASSERT_ERR(band == PHY_BAND_2G4); @@ -222,19 +213,6 @@ void phy_hw_set_channel(uint8_t band, uint16_t freq, uint16_t freq1, uint8_t cha uint8_t channel = 0; - /* - int iVar3 = 0; - if (band == PHY_BAND_2G4) { - if ((freq - 0x96cU & 0xffff) >= 0x48) { - channel = 0xe; - if (freq != 0x9b4) { - channel = (uint8_t)((freq -0x967) / 5); - } - } - - } - */ - // TODO: are these two functions equivelant??? channel = phy_freq_to_channel(band, freq); rfc_apply_tx_power_offset(channel, poweroffset); trpc_update_vs_channel((int8_t)freq1); @@ -315,17 +293,17 @@ void phy_init(phy_cfg_tag *config) { phy_tcal_start(); } -uint8_t phy_vht_supported(){ +uint8_t phy_vht_supported() { if (MDM->version.vht) // TODO: verify this cond return 1; return ((MDM->version.chbw) >> 1) & 1; } -uint8_t phy_ldpc_rx_supported(void){ +uint8_t phy_ldpc_rx_supported(void) { return MDM->version.ldpcrx; } -uint8_t phy_ldpc_tx_supported(void){ +uint8_t phy_ldpc_tx_supported(void) { return MDM->version.ldpctx; } @@ -353,6 +331,6 @@ void phy_reset(void) { return ; } -void phy_stop(void){ +void phy_stop(void) { return ; } diff --git a/src/bl602_wifi/phy_bl602.h b/src/bl602_wifi/phy_bl602.h index c0758f3..2bf1a40 100644 --- a/src/bl602_wifi/phy_bl602.h +++ b/src/bl602_wifi/phy_bl602.h @@ -21,6 +21,13 @@ enum PHY_CHNL_BW_OTHER, }; +enum +{ + PHY_FORMATMOD_11B, + PHY_FORMATMOD_11G, + PHY_FORMATMOD_11N, +}; + struct phy_channel_info { /// PHY channel information 1 @@ -53,7 +60,6 @@ struct phy_env_tag phy_env[1]; // :75:20 void phy_config_rxgain(int offset); uint8_t phy_get_mac_freq(); void phy_get_channel(struct phy_channel_info *info, uint8_t index); -uint8_t phy_get_mac_freq(void); uint8_t phy_get_nss(void); void phy_get_version(uint32_t *version_1,uint32_t *version_2); void agc_config(void); @@ -62,4 +68,72 @@ void mpif_clk_init(void); uint8_t phy_vht_supported(); uint8_t phy_get_ntx(void); uint8_t phy_get_nss(void); +void phy_stop(void); +void phy_reset(void); +void phy_rc_isr(void); +uint8_t phy_mu_mimo_tx_supported(void); +uint8_t phy_mu_mimo_rx_supported(void); +void phy_mdm_isr(void); +uint8_t phy_ldpc_tx_supported(void); +uint8_t phy_ldpc_rx_supported(void); +void phy_init(phy_cfg_tag *config); +void phy_set_channel(uint8_t band,uint8_t type,uint16_t prim20_freq,uint16_t center1_freq, + uint16_t center2_freq,uint8_t index); +void phy_hw_set_channel(uint8_t band, uint16_t freq, uint16_t freq1, uint8_t chantype); + +void phy_powroffset_set(int8_t *power_offset); +void phy_get_trpc_idx(uint8_t formatmod,uint8_t mcs,int8_t power,uint8_t *idx); +void phy_get_rf_gain_idx_vs_mode(uint8_t mode,int8_t *power,uint8_t *idx); +void phy_get_rf_gain_idx(int8_t *power,uint8_t *idx); +void phy_get_rf_gain_capab(int8_t *max,int8_t *min); +uint8_t phy_bfmer_supported(void); +uint8_t phy_bfmee_supported(); +void mpif_clk_init(void); +void bz_phy_reset(void); + +// not sure if there functions are belong to phy_bl602 +// but they seem to be inlined in many funcs + +int static phy_freq_to_channel(uint8_t band, uint16_t freq) { + int base = 0; + if (band == 0) { + // 2.4GHz + if (freq == 2484) + return 14; + if (freq - 2407 > 65) + return 0; + base = -2407; + } else { + if (band == 1) { + // 5GHz + if (freq > 5825) + return 0; + base = -5000; + } else return 0; + } + return (((int)freq) + base) / 5; +} + + +uint16_t static phy_channel_to_freq(uint8_t band, int channel) { + int freq = 0; + if (band == 0) { + // 2.4GHz + if (channel > 14) { + return 0xffff; + } + if (channel == 14) { + return 2484; + } + freq = 2407; + } else { + // 5GHz + if (channel > 165) { + return 0xffff; + } + freq = 5000; + } + return channel * 5 + freq; +} + #endif \ No newline at end of file diff --git a/src/bl602_wifi/phy_hal.h b/src/bl602_wifi/phy_hal.h new file mode 100644 index 0000000..71902e5 --- /dev/null +++ b/src/bl602_wifi/phy_hal.h @@ -0,0 +1,17 @@ +#ifndef _PHY_HAL_H_ +#define _PHY_HAL_H_ +#include +struct phy_hal_tag { + int16_t temperature; // +0 + uint8_t capcode; // +2 +}; // :6:8 + +//static struct phy_hal_tag hal_env; // :15:27 + +uint8_t hal_get_capcode(void); // :43:9 +void hal_set_capcode(uint32_t capcode); // :48:6 +void hal_set_capcode_asymm(uint32_t capcode_in, uint32_t capcode_out); // :55:6 +void hal_get_capcode_asymm(uint8_t *capcode_in, uint8_t *capcode_out); // :64:6 +bool hal_get_temperature(int16_t *temperature); // :75:5 +void hal_set_temperature(int16_t temperature); // :83:6 +#endif \ No newline at end of file diff --git a/src/bl602_wifi/utils.h b/src/bl602_wifi/utils.h new file mode 100644 index 0000000..fe930e2 --- /dev/null +++ b/src/bl602_wifi/utils.h @@ -0,0 +1,3 @@ +#ifndef __UTILS_H_ +#define ABS(x) (((x) > 0) ? (x) : (-(x))) +#endif \ No newline at end of file diff --git a/src/include/stdint.h b/src/include/stdint.h index 866d0cb..b71c7c3 100644 --- a/src/include/stdint.h +++ b/src/include/stdint.h @@ -7,8 +7,8 @@ typedef unsigned int uint32_t; typedef unsigned long long int uint64_t; typedef signed char int8_t; -typedef short intint16_t; +typedef short int16_t; typedef int int32_t; typedef long long int int64_t; - +typedef uint8_t bool; #endif \ No newline at end of file From e7b27cec4458e81148bd134bfd69645a6bcda3a4 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sat, 24 Jul 2021 21:49:47 -0500 Subject: [PATCH 037/148] fix error and warn --- src/bl602_wifi/hal_desc.h | 1 + src/bl602_wifi/phy.h | 8 ++++++++ src/bl602_wifi/phy_adapt.c | 2 +- src/bl602_wifi/phy_bl602.h | 10 +--------- 4 files changed, 11 insertions(+), 10 deletions(-) create mode 100644 src/bl602_wifi/phy.h diff --git a/src/bl602_wifi/hal_desc.h b/src/bl602_wifi/hal_desc.h index 6a68565..849e16b 100644 --- a/src/bl602_wifi/hal_desc.h +++ b/src/bl602_wifi/hal_desc.h @@ -2,6 +2,7 @@ #ifndef _HAL_DESC_H_ #define _HAL_DESC_H_ #include +#include "phy.h" struct tx_policy_tbl { uint32_t upatterntx; // +0 uint32_t phycntrlinfo1; // +4 diff --git a/src/bl602_wifi/phy.h b/src/bl602_wifi/phy.h new file mode 100644 index 0000000..db83a71 --- /dev/null +++ b/src/bl602_wifi/phy.h @@ -0,0 +1,8 @@ +#ifndef _PHY_H_ +#define _PHY_H_ +#include +struct phy_channel_info { + uint32_t info1; // +0 + uint32_t info2; // +4 +}; // :97:8 +#endif \ No newline at end of file diff --git a/src/bl602_wifi/phy_adapt.c b/src/bl602_wifi/phy_adapt.c index 3f5d671..8235b71 100644 --- a/src/bl602_wifi/phy_adapt.c +++ b/src/bl602_wifi/phy_adapt.c @@ -136,7 +136,7 @@ float calc_ppm(rvec_t * rvec) { void pa_input(uint8_t id, struct rx_hd *rhd) { if (id < 4) { int ptr = pa_env[id].input_buffer_ptr; - rvec_t *rvec = &(rhd->recvec1a); + rvec_t *rvec = (rvec_t *)&(rhd->recvec1a); input_t *buffer = &(pa_env[id].input_buffer[ptr]); pa_env[id].last_update = rhd->tsflo; buffer->new = 1; diff --git a/src/bl602_wifi/phy_bl602.h b/src/bl602_wifi/phy_bl602.h index 2bf1a40..dfd8b48 100644 --- a/src/bl602_wifi/phy_bl602.h +++ b/src/bl602_wifi/phy_bl602.h @@ -1,6 +1,6 @@ #ifndef _PHY_BL602_H_ #include - +#include "phy.h" enum { /// 2.4GHz Band @@ -28,14 +28,6 @@ enum PHY_FORMATMOD_11N, }; -struct phy_channel_info -{ - /// PHY channel information 1 - uint32_t info1; - /// PHY channel information 2 - uint32_t info2; -}; - typedef struct phy_cfg_tag phy_cfg_tag; struct phy_cfg_tag { From 81745e56fde135869c2a96290512c90a7faf43ad Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sat, 24 Jul 2021 22:12:44 -0500 Subject: [PATCH 038/148] add offset fixed svd --- .../Bouffalo/BL602/Peripherals/soc602_reg.svd | 19921 ++++++++++++++++ 1 file changed, 19921 insertions(+) create mode 100644 components/bl602/bl602_std/bl602_std/Device/Bouffalo/BL602/Peripherals/soc602_reg.svd diff --git a/components/bl602/bl602_std/bl602_std/Device/Bouffalo/BL602/Peripherals/soc602_reg.svd b/components/bl602/bl602_std/bl602_std/Device/Bouffalo/BL602/Peripherals/soc602_reg.svd new file mode 100644 index 0000000..a04a85a --- /dev/null +++ b/components/bl602/bl602_std/bl602_std/Device/Bouffalo/BL602/Peripherals/soc602_reg.svd @@ -0,0 +1,19921 @@ + + + bouffalolab + bouffalolab + 602 + WiFi BT + high-performance, 32-bit RV32IMAFC core + 8 + 32 + 32 + 0x00000000 + 0xFFFFFFFF + + 602 + little + + + + glb + glb. + 0x40000000 + glb + 32 + read-write + + 0 + 0x1000 + registers + + + + clk_cfg0 + clk_cfg0. + 0x0 + + + glb_id + 28 + 31 + + + chip_rdy + 27 + 27 + + + fclk_sw_state + 24 + 26 + + + reg_bclk_div + 16 + 23 + + + reg_hclk_div + 8 + 15 + + + hbn_root_clk_sel + 6 + 7 + + + reg_pll_sel + 4 + 5 + + + reg_bclk_en + 3 + 3 + + + reg_hclk_en + 2 + 2 + + + reg_fclk_en + 1 + 1 + + + reg_pll_en + 0 + 0 + + + + + clk_cfg1 + clk_cfg1. + 0x4 + + + ble_en + 24 + 24 + + + ble_clk_sel + 16 + 21 + + + wifi_mac_wt_div + 4 + 7 + + + wifi_mac_core_div + 0 + 3 + + + + + clk_cfg2 + clk_cfg2. + 0x8 + + + dma_clk_en + 24 + 31 + + + ir_clk_en + 23 + 23 + + + ir_clk_div + 16 + 21 + + + sf_clk_sel2 + 14 + 15 + + + sf_clk_sel + 12 + 13 + + + sf_clk_en + 11 + 11 + + + sf_clk_div + 8 + 10 + + + hbn_uart_clk_sel + 7 + 7 + + + uart_clk_en + 4 + 4 + + + uart_clk_div + 0 + 2 + + + + + clk_cfg3 + clk_cfg3. + 0xC + + + i2c_clk_en + 24 + 24 + + + i2c_clk_div + 16 + 23 + + + spi_clk_en + 8 + 8 + + + spi_clk_div + 0 + 4 + + + + + swrst_cfg0 + swrst_cfg0. + 0x10 + + + swrst_s30 + 8 + 8 + + + swrst_s20 + 4 + 4 + + + swrst_s01 + 1 + 1 + + + swrst_s00 + 0 + 0 + + + + + swrst_cfg1 + swrst_cfg1. + 0x14 + + + swrst_s1a7 + 23 + 23 + + + swrst_s1a6 + 22 + 22 + + + swrst_s1a5 + 21 + 21 + + + swrst_s1a4 + 20 + 20 + + + swrst_s1a3 + 19 + 19 + + + swrst_s1a2 + 18 + 18 + + + swrst_s1a1 + 17 + 17 + + + swrst_s1a0 + 16 + 16 + + + swrst_s1f + 15 + 15 + + + swrst_s1e + 14 + 14 + + + swrst_s1d + 13 + 13 + + + swrst_s1c + 12 + 12 + + + swrst_s1b + 11 + 11 + + + swrst_s1a + 10 + 10 + + + swrst_s19 + 9 + 9 + + + swrst_s18 + 8 + 8 + + + swrst_s17 + 7 + 7 + + + swrst_s16 + 6 + 6 + + + swrst_s15 + 5 + 5 + + + swrst_s14 + 4 + 4 + + + swrst_s13 + 3 + 3 + + + swrst_s12 + 2 + 2 + + + swrst_s11 + 1 + 1 + + + swrst_s10 + 0 + 0 + + + + + swrst_cfg2 + swrst_cfg2. + 0x18 + + + pka_clk_sel + 24 + 24 + + + reg_ctrl_reset_dummy + 4 + 7 + + + reg_ctrl_sys_reset + 2 + 2 + + + reg_ctrl_cpu_reset + 1 + 1 + + + reg_ctrl_pwron_rst + 0 + 0 + + + + + swrst_cfg3 + swrst_cfg3. + 0x1C + + + + cgen_cfg0 + cgen_cfg0. + 0x20 + + + cgen_m + 0 + 7 + + + + + cgen_cfg1 + cgen_cfg1. + 0x24 + + + cgen_s1a + 16 + 23 + + + cgen_s1 + 0 + 15 + + + + + cgen_cfg2 + cgen_cfg2. + 0x28 + + + cgen_s3 + 4 + 4 + + + cgen_s2 + 0 + 0 + + + + + cgen_cfg3 + cgen_cfg3. + 0x2C + + + + MBIST_CTL + MBIST_CTL. + 0x30 + + + reg_mbist_rst_n + 31 + 31 + + + wifi_mbist_mode + 4 + 4 + + + ocram_mbist_mode + 3 + 3 + + + tag_mbist_mode + 2 + 2 + + + hsram_mbist_mode + 1 + 1 + + + irom_mbist_mode + 0 + 0 + + + + + MBIST_STAT + MBIST_STAT. + 0x34 + + + wifi_mbist_fail + 20 + 20 + + + ocram_mbist_fail + 19 + 19 + + + tag_mbist_fail + 18 + 18 + + + hsram_mbist_fail + 17 + 17 + + + irom_mbist_fail + 16 + 16 + + + wifi_mbist_done + 4 + 4 + + + ocram_mbist_done + 3 + 3 + + + tag_mbist_done + 2 + 2 + + + hsram_mbist_done + 1 + 1 + + + irom_mbist_done + 0 + 0 + + + + + bmx_cfg1 + bmx_cfg1. + 0x50 + + + hbn_apb_cfg + 24 + 31 + + + pds_apb_cfg + 16 + 23 + + + hsel_option + 12 + 15 + + + bmx_gating_dis + 10 + 10 + + + bmx_busy_option_dis + 9 + 9 + + + bmx_err_en + 8 + 8 + + + bmx_arb_mode + 4 + 5 + + + bmx_timeout_en + 0 + 3 + + + + + bmx_cfg2 + bmx_cfg2. + 0x54 + + + bmx_dbg_sel + 28 + 31 + + + bmx_err_tz + 5 + 5 + + + bmx_err_dec + 4 + 4 + + + bmx_err_addr_dis + 0 + 0 + + + + + bmx_err_addr + bmx_err_addr. + 0x58 + + + bmx_err_addr + 0 + 31 + + + + + bmx_dbg_out + bmx_dbg_out. + 0x5C + + + bmx_dbg_out + 0 + 31 + + + + + rsv0 + rsv0. + 0x60 + + + rsvd_31_0 + 0 + 31 + + + + + rsv1 + rsv1. + 0x64 + + + rsvd_31_0 + 0 + 31 + + + + + rsv2 + rsv2. + 0x68 + + + rsvd_31_0 + 0 + 31 + + + + + rsv3 + rsv3. + 0x6C + + + rsvd_31_0 + 0 + 31 + + + + + sram_ret + sram_ret. + 0x70 + + + reg_sram_ret + 0 + 31 + + + + + sram_slp + sram_slp. + 0x74 + + + reg_sram_slp + 0 + 31 + + + + + sram_parm + sram_parm. + 0x78 + + + reg_sram_parm + 0 + 31 + + + + + seam_misc + seam_misc. + 0x7C + + + em_sel + 0 + 3 + + + + + glb_parm + glb_parm. + 0x80 + + + uart_swap_set + 24 + 26 + + + p7_jtag_use_io_2_5 + 23 + 23 + + + p6_sdio_use_io_0_5 + 22 + 22 + + + p5_dac_test_with_jtag + 21 + 21 + + + p4_adc_test_with_jtag + 20 + 20 + + + p3_cci_use_io_2_5 + 19 + 19 + + + p2_dac_test_with_cci + 18 + 18 + + + p1_adc_test_with_cci + 17 + 17 + + + reg_cci_use_sdio_pin + 16 + 16 + + + reg_cci_use_jtag_pin + 15 + 15 + + + reg_spi_0_swap + 13 + 13 + + + reg_spi_0_master_mode + 12 + 12 + + + sel_embedded_sflash + 9 + 9 + + + swap_sflash_io_3_io_0 + 8 + 8 + + + jtag_swap_set + 2 + 7 + + + reg_ext_rst_smt + 1 + 1 + + + reg_bd_en + 0 + 0 + + + + + CPU_CLK_CFG + CPU_CLK_CFG. + 0x90 + + + debug_ndreset_gate + 20 + 20 + + + cpu_rtc_sel + 19 + 19 + + + cpu_rtc_en + 18 + 18 + + + cpu_rtc_div + 0 + 16 + + + + + GPADC_32M_SRC_CTRL + GPADC_32M_SRC_CTRL. + 0xA4 + + + gpadc_32m_div_en + 8 + 8 + + + gpadc_32m_clk_sel + 7 + 7 + + + gpadc_32m_clk_div + 0 + 5 + + + + + DIG32K_WAKEUP_CTRL + DIG32K_WAKEUP_CTRL. + 0xA8 + + + reg_en_platform_wakeup + 31 + 31 + + + dig_clk_src_sel + 28 + 28 + + + dig_512k_comp + 25 + 25 + + + dig_512k_en + 24 + 24 + + + dig_512k_div + 16 + 22 + + + dig_32k_comp + 13 + 13 + + + dig_32k_en + 12 + 12 + + + dig_32k_div + 0 + 10 + + + + + WIFI_BT_COEX_CTRL + WIFI_BT_COEX_CTRL. + 0xAC + + + en_gpio_bt_coex + 12 + 12 + + + coex_bt_bw + 11 + 11 + + + coex_bt_pti + 7 + 10 + + + coex_bt_channel + 0 + 6 + + + + + UART_SIG_SEL_0 + UART_SIG_SEL_0. + 0xC0 + + + uart_sig_7_sel + 28 + 31 + + + uart_sig_6_sel + 24 + 27 + + + uart_sig_5_sel + 20 + 23 + + + uart_sig_4_sel + 16 + 19 + + + uart_sig_3_sel + 12 + 15 + + + uart_sig_2_sel + 8 + 11 + + + uart_sig_1_sel + 4 + 7 + + + uart_sig_0_sel + 0 + 3 + + + + + DBG_SEL_LL + DBG_SEL_LL. + 0xD0 + + + reg_dbg_ll_ctrl + 0 + 31 + + + + + DBG_SEL_LH + DBG_SEL_LH. + 0xD4 + + + reg_dbg_lh_ctrl + 0 + 31 + + + + + DBG_SEL_HL + DBG_SEL_HL. + 0xD8 + + + reg_dbg_hl_ctrl + 0 + 31 + + + + + DBG_SEL_HH + DBG_SEL_HH. + 0xDC + + + reg_dbg_hh_ctrl + 0 + 31 + + + + + debug + debug. + 0xE0 + + + debug_i + 1 + 31 + + + debug_oe + 0 + 0 + + + + + GPIO_CFGCTL0 + GPIO_CFGCTL0. + 0x100 + + + real_gpio_1_func_sel + 28 + 31 + + + reg_gpio_1_func_sel + 24 + 27 + + + reg_gpio_1_pd + 21 + 21 + + + reg_gpio_1_pu + 20 + 20 + + + reg_gpio_1_drv + 18 + 19 + + + reg_gpio_1_smt + 17 + 17 + + + reg_gpio_1_ie + 16 + 16 + + + real_gpio_0_func_sel + 12 + 15 + + + reg_gpio_0_func_sel + 8 + 11 + + + reg_gpio_0_pd + 5 + 5 + + + reg_gpio_0_pu + 4 + 4 + + + reg_gpio_0_drv + 2 + 3 + + + reg_gpio_0_smt + 1 + 1 + + + reg_gpio_0_ie + 0 + 0 + + + + + GPIO_CFGCTL1 + GPIO_CFGCTL1. + 0x104 + + + real_gpio_3_func_sel + 28 + 31 + + + reg_gpio_3_func_sel + 24 + 27 + + + reg_gpio_3_pd + 21 + 21 + + + reg_gpio_3_pu + 20 + 20 + + + reg_gpio_3_drv + 18 + 19 + + + reg_gpio_3_smt + 17 + 17 + + + reg_gpio_3_ie + 16 + 16 + + + real_gpio_2_func_sel + 12 + 15 + + + reg_gpio_2_func_sel + 8 + 11 + + + reg_gpio_2_pd + 5 + 5 + + + reg_gpio_2_pu + 4 + 4 + + + reg_gpio_2_drv + 2 + 3 + + + reg_gpio_2_smt + 1 + 1 + + + reg_gpio_2_ie + 0 + 0 + + + + + GPIO_CFGCTL2 + GPIO_CFGCTL2. + 0x108 + + + real_gpio_5_func_sel + 28 + 31 + + + reg_gpio_5_func_sel + 24 + 27 + + + reg_gpio_5_pd + 21 + 21 + + + reg_gpio_5_pu + 20 + 20 + + + reg_gpio_5_drv + 18 + 19 + + + reg_gpio_5_smt + 17 + 17 + + + reg_gpio_5_ie + 16 + 16 + + + real_gpio_4_func_sel + 12 + 15 + + + reg_gpio_4_func_sel + 8 + 11 + + + reg_gpio_4_pd + 5 + 5 + + + reg_gpio_4_pu + 4 + 4 + + + reg_gpio_4_drv + 2 + 3 + + + reg_gpio_4_smt + 1 + 1 + + + reg_gpio_4_ie + 0 + 0 + + + + + GPIO_CFGCTL3 + GPIO_CFGCTL3. + 0x10C + + + reg_gpio_7_func_sel + 24 + 27 + + + reg_gpio_7_pd + 21 + 21 + + + reg_gpio_7_pu + 20 + 20 + + + reg_gpio_7_drv + 18 + 19 + + + reg_gpio_7_smt + 17 + 17 + + + reg_gpio_7_ie + 16 + 16 + + + reg_gpio_6_func_sel + 8 + 11 + + + reg_gpio_6_pd + 5 + 5 + + + reg_gpio_6_pu + 4 + 4 + + + reg_gpio_6_drv + 2 + 3 + + + reg_gpio_6_smt + 1 + 1 + + + reg_gpio_6_ie + 0 + 0 + + + + + GPIO_CFGCTL4 + GPIO_CFGCTL4. + 0x110 + + + reg_gpio_9_func_sel + 24 + 27 + + + reg_gpio_9_pd + 21 + 21 + + + reg_gpio_9_pu + 20 + 20 + + + reg_gpio_9_drv + 18 + 19 + + + reg_gpio_9_smt + 17 + 17 + + + reg_gpio_9_ie + 16 + 16 + + + reg_gpio_8_func_sel + 8 + 11 + + + reg_gpio_8_pd + 5 + 5 + + + reg_gpio_8_pu + 4 + 4 + + + reg_gpio_8_drv + 2 + 3 + + + reg_gpio_8_smt + 1 + 1 + + + reg_gpio_8_ie + 0 + 0 + + + + + GPIO_CFGCTL5 + GPIO_CFGCTL5. + 0x114 + + + reg_gpio_11_func_sel + 24 + 27 + + + reg_gpio_11_pd + 21 + 21 + + + reg_gpio_11_pu + 20 + 20 + + + reg_gpio_11_drv + 18 + 19 + + + reg_gpio_11_smt + 17 + 17 + + + reg_gpio_11_ie + 16 + 16 + + + reg_gpio_10_func_sel + 8 + 11 + + + reg_gpio_10_pd + 5 + 5 + + + reg_gpio_10_pu + 4 + 4 + + + reg_gpio_10_drv + 2 + 3 + + + reg_gpio_10_smt + 1 + 1 + + + reg_gpio_10_ie + 0 + 0 + + + + + GPIO_CFGCTL6 + GPIO_CFGCTL6. + 0x118 + + + reg_gpio_13_func_sel + 24 + 27 + + + reg_gpio_13_pd + 21 + 21 + + + reg_gpio_13_pu + 20 + 20 + + + reg_gpio_13_drv + 18 + 19 + + + reg_gpio_13_smt + 17 + 17 + + + reg_gpio_13_ie + 16 + 16 + + + reg_gpio_12_func_sel + 8 + 11 + + + reg_gpio_12_pd + 5 + 5 + + + reg_gpio_12_pu + 4 + 4 + + + reg_gpio_12_drv + 2 + 3 + + + reg_gpio_12_smt + 1 + 1 + + + reg_gpio_12_ie + 0 + 0 + + + + + GPIO_CFGCTL7 + GPIO_CFGCTL7. + 0x11C + + + reg_gpio_15_func_sel + 24 + 27 + + + reg_gpio_15_pd + 21 + 21 + + + reg_gpio_15_pu + 20 + 20 + + + reg_gpio_15_drv + 18 + 19 + + + reg_gpio_15_smt + 17 + 17 + + + reg_gpio_15_ie + 16 + 16 + + + reg_gpio_14_func_sel + 8 + 11 + + + reg_gpio_14_pd + 5 + 5 + + + reg_gpio_14_pu + 4 + 4 + + + reg_gpio_14_drv + 2 + 3 + + + reg_gpio_14_smt + 1 + 1 + + + reg_gpio_14_ie + 0 + 0 + + + + + GPIO_CFGCTL8 + GPIO_CFGCTL8. + 0x120 + + + reg_gpio_17_func_sel + 24 + 27 + + + reg_gpio_17_pd + 21 + 21 + + + reg_gpio_17_pu + 20 + 20 + + + reg_gpio_17_drv + 18 + 19 + + + reg_gpio_17_smt + 17 + 17 + + + reg_gpio_17_ie + 16 + 16 + + + reg_gpio_16_func_sel + 8 + 11 + + + reg_gpio_16_pd + 5 + 5 + + + reg_gpio_16_pu + 4 + 4 + + + reg_gpio_16_drv + 2 + 3 + + + reg_gpio_16_smt + 1 + 1 + + + reg_gpio_16_ie + 0 + 0 + + + + + GPIO_CFGCTL9 + GPIO_CFGCTL9. + 0x124 + + + reg_gpio_19_func_sel + 24 + 27 + + + reg_gpio_19_pd + 21 + 21 + + + reg_gpio_19_pu + 20 + 20 + + + reg_gpio_19_drv + 18 + 19 + + + reg_gpio_19_smt + 17 + 17 + + + reg_gpio_19_ie + 16 + 16 + + + reg_gpio_18_func_sel + 8 + 11 + + + reg_gpio_18_pd + 5 + 5 + + + reg_gpio_18_pu + 4 + 4 + + + reg_gpio_18_drv + 2 + 3 + + + reg_gpio_18_smt + 1 + 1 + + + reg_gpio_18_ie + 0 + 0 + + + + + GPIO_CFGCTL10 + GPIO_CFGCTL10. + 0x128 + + + reg_gpio_21_func_sel + 24 + 27 + + + reg_gpio_21_pd + 21 + 21 + + + reg_gpio_21_pu + 20 + 20 + + + reg_gpio_21_drv + 18 + 19 + + + reg_gpio_21_smt + 17 + 17 + + + reg_gpio_21_ie + 16 + 16 + + + reg_gpio_20_func_sel + 8 + 11 + + + reg_gpio_20_pd + 5 + 5 + + + reg_gpio_20_pu + 4 + 4 + + + reg_gpio_20_drv + 2 + 3 + + + reg_gpio_20_smt + 1 + 1 + + + reg_gpio_20_ie + 0 + 0 + + + + + GPIO_CFGCTL11 + GPIO_CFGCTL11. + 0x12C + + + reg_gpio_23_pd + 21 + 21 + + + reg_gpio_23_pu + 20 + 20 + + + reg_gpio_23_drv + 18 + 19 + + + reg_gpio_23_smt + 17 + 17 + + + reg_gpio_23_ie + 16 + 16 + + + reg_gpio_22_func_sel + 8 + 11 + + + reg_gpio_22_pd + 5 + 5 + + + reg_gpio_22_pu + 4 + 4 + + + reg_gpio_22_drv + 2 + 3 + + + reg_gpio_22_smt + 1 + 1 + + + reg_gpio_22_ie + 0 + 0 + + + + + GPIO_CFGCTL12 + GPIO_CFGCTL12. + 0x130 + + + reg_gpio_25_pd + 21 + 21 + + + reg_gpio_25_pu + 20 + 20 + + + reg_gpio_25_drv + 18 + 19 + + + reg_gpio_25_smt + 17 + 17 + + + reg_gpio_25_ie + 16 + 16 + + + reg_gpio_24_pd + 5 + 5 + + + reg_gpio_24_pu + 4 + 4 + + + reg_gpio_24_drv + 2 + 3 + + + reg_gpio_24_smt + 1 + 1 + + + reg_gpio_24_ie + 0 + 0 + + + + + GPIO_CFGCTL13 + GPIO_CFGCTL13. + 0x134 + + + reg_gpio_27_pd + 21 + 21 + + + reg_gpio_27_pu + 20 + 20 + + + reg_gpio_27_drv + 18 + 19 + + + reg_gpio_27_smt + 17 + 17 + + + reg_gpio_27_ie + 16 + 16 + + + reg_gpio_26_pd + 5 + 5 + + + reg_gpio_26_pu + 4 + 4 + + + reg_gpio_26_drv + 2 + 3 + + + reg_gpio_26_smt + 1 + 1 + + + reg_gpio_26_ie + 0 + 0 + + + + + GPIO_CFGCTL14 + GPIO_CFGCTL14. + 0x138 + + + reg_gpio_28_pd + 5 + 5 + + + reg_gpio_28_pu + 4 + 4 + + + reg_gpio_28_drv + 2 + 3 + + + reg_gpio_28_smt + 1 + 1 + + + reg_gpio_28_ie + 0 + 0 + + + + + GPIO_CFGCTL30 + GPIO_CFGCTL30. + 0x180 + + + reg_gpio_22_i + 22 + 22 + + + reg_gpio_21_i + 21 + 21 + + + reg_gpio_20_i + 20 + 20 + + + reg_gpio_19_i + 19 + 19 + + + reg_gpio_18_i + 18 + 18 + + + reg_gpio_17_i + 17 + 17 + + + reg_gpio_16_i + 16 + 16 + + + reg_gpio_15_i + 15 + 15 + + + reg_gpio_14_i + 14 + 14 + + + reg_gpio_13_i + 13 + 13 + + + reg_gpio_12_i + 12 + 12 + + + reg_gpio_11_i + 11 + 11 + + + reg_gpio_10_i + 10 + 10 + + + reg_gpio_9_i + 9 + 9 + + + reg_gpio_8_i + 8 + 8 + + + reg_gpio_7_i + 7 + 7 + + + reg_gpio_6_i + 6 + 6 + + + reg_gpio_5_i + 5 + 5 + + + reg_gpio_4_i + 4 + 4 + + + reg_gpio_3_i + 3 + 3 + + + reg_gpio_2_i + 2 + 2 + + + reg_gpio_1_i + 1 + 1 + + + reg_gpio_0_i + 0 + 0 + + + + + GPIO_CFGCTL31 + GPIO_CFGCTL31. + 0x184 + + + + GPIO_CFGCTL32 + GPIO_CFGCTL32. + 0x188 + + + reg_gpio_22_o + 22 + 22 + + + reg_gpio_21_o + 21 + 21 + + + reg_gpio_20_o + 20 + 20 + + + reg_gpio_19_o + 19 + 19 + + + reg_gpio_18_o + 18 + 18 + + + reg_gpio_17_o + 17 + 17 + + + reg_gpio_16_o + 16 + 16 + + + reg_gpio_15_o + 15 + 15 + + + reg_gpio_14_o + 14 + 14 + + + reg_gpio_13_o + 13 + 13 + + + reg_gpio_12_o + 12 + 12 + + + reg_gpio_11_o + 11 + 11 + + + reg_gpio_10_o + 10 + 10 + + + reg_gpio_9_o + 9 + 9 + + + reg_gpio_8_o + 8 + 8 + + + reg_gpio_7_o + 7 + 7 + + + reg_gpio_6_o + 6 + 6 + + + reg_gpio_5_o + 5 + 5 + + + reg_gpio_4_o + 4 + 4 + + + reg_gpio_3_o + 3 + 3 + + + reg_gpio_2_o + 2 + 2 + + + reg_gpio_1_o + 1 + 1 + + + reg_gpio_0_o + 0 + 0 + + + + + GPIO_CFGCTL33 + GPIO_CFGCTL33. + 0x18C + + + + GPIO_CFGCTL34 + GPIO_CFGCTL34. + 0x190 + + + reg_gpio_22_oe + 22 + 22 + + + reg_gpio_21_oe + 21 + 21 + + + reg_gpio_20_oe + 20 + 20 + + + reg_gpio_19_oe + 19 + 19 + + + reg_gpio_18_oe + 18 + 18 + + + reg_gpio_17_oe + 17 + 17 + + + reg_gpio_16_oe + 16 + 16 + + + reg_gpio_15_oe + 15 + 15 + + + reg_gpio_14_oe + 14 + 14 + + + reg_gpio_13_oe + 13 + 13 + + + reg_gpio_12_oe + 12 + 12 + + + reg_gpio_11_oe + 11 + 11 + + + reg_gpio_10_oe + 10 + 10 + + + reg_gpio_9_oe + 9 + 9 + + + reg_gpio_8_oe + 8 + 8 + + + reg_gpio_7_oe + 7 + 7 + + + reg_gpio_6_oe + 6 + 6 + + + reg_gpio_5_oe + 5 + 5 + + + reg_gpio_4_oe + 4 + 4 + + + reg_gpio_3_oe + 3 + 3 + + + reg_gpio_2_oe + 2 + 2 + + + reg_gpio_1_oe + 1 + 1 + + + reg_gpio_0_oe + 0 + 0 + + + + + GPIO_CFGCTL35 + GPIO_CFGCTL35. + 0x194 + + + + GPIO_INT_MASK1 + GPIO_INT_MASK1. + 0x1A0 + + + reg_gpio_int_mask1 + 0 + 31 + + + + + GPIO_INT_STAT1 + GPIO_INT_STAT1. + 0x1A8 + + + gpio_int_stat1 + 0 + 31 + + + + + GPIO_INT_CLR1 + GPIO_INT_CLR1. + 0x1B0 + + + reg_gpio_int_clr1 + 0 + 31 + + + + + GPIO_INT_MODE_SET1 + GPIO_INT_MODE_SET1. + 0x1C0 + + + reg_gpio_int_mode_set1 + 0 + 31 + + + + + GPIO_INT_MODE_SET2 + GPIO_INT_MODE_SET2. + 0x1C4 + + + reg_gpio_int_mode_set2 + 0 + 31 + + + + + GPIO_INT_MODE_SET3 + GPIO_INT_MODE_SET3. + 0x1C8 + + + reg_gpio_int_mode_set3 + 0 + 31 + + + + + led_driver + led_driver. + 0x224 + + + pu_leddrv + 31 + 31 + + + ir_rx_gpio_sel + 8 + 9 + + + leddrv_ibias + 4 + 7 + + + led_din_polarity_sel + 2 + 2 + + + led_din_sel + 1 + 1 + + + led_din_reg + 0 + 0 + + + + + gpdac_ctrl + gpdac_ctrl. + 0x308 + + + gpdac_reserved + 24 + 31 + + + gpdac_test_sel + 9 + 11 + + + gpdac_ref_sel + 8 + 8 + + + gpdac_test_en + 7 + 7 + + + gpdacb_rstn_ana + 1 + 1 + + + gpdaca_rstn_ana + 0 + 0 + + + + + gpdac_actrl + gpdac_actrl. + 0x30C + + + gpdac_a_outmux + 20 + 22 + + + gpdac_a_rng + 18 + 19 + + + gpdac_ioa_en + 1 + 1 + + + gpdac_a_en + 0 + 0 + + + + + gpdac_bctrl + gpdac_bctrl. + 0x310 + + + gpdac_b_outmux + 20 + 22 + + + gpdac_b_rng + 18 + 19 + + + gpdac_iob_en + 1 + 1 + + + gpdac_b_en + 0 + 0 + + + + + gpdac_data + gpdac_data. + 0x314 + + + gpdac_a_data + 16 + 25 + + + gpdac_b_data + 0 + 9 + + + + + tzc_glb_ctrl_0 + tzc_glb_ctrl_0. + 0xF00 + + + tzc_glb_clk_lock + 31 + 31 + + + tzc_glb_mbist_lock + 30 + 30 + + + tzc_glb_dbg_lock + 29 + 29 + + + tzc_glb_bmx_lock + 28 + 28 + + + tzc_glb_l2c_lock + 27 + 27 + + + tzc_glb_sram_lock + 26 + 26 + + + tzc_glb_misc_lock + 25 + 25 + + + tzc_glb_ctrl_ungated_ap_lock + 15 + 15 + + + tzc_glb_ctrl_sys_reset_lock + 14 + 14 + + + tzc_glb_ctrl_cpu_reset_lock + 13 + 13 + + + tzc_glb_ctrl_pwron_rst_lock + 12 + 12 + + + tzc_glb_swrst_s30_lock + 8 + 8 + + + tzc_glb_swrst_s01_lock + 1 + 1 + + + tzc_glb_swrst_s00_lock + 0 + 0 + + + + + tzc_glb_ctrl_1 + tzc_glb_ctrl_1. + 0xF04 + + + tzc_glb_swrst_s1f_lock + 31 + 31 + + + tzc_glb_swrst_s1e_lock + 30 + 30 + + + tzc_glb_swrst_s1d_lock + 29 + 29 + + + tzc_glb_swrst_s1c_lock + 28 + 28 + + + tzc_glb_swrst_s1b_lock + 27 + 27 + + + tzc_glb_swrst_s1a_lock + 26 + 26 + + + tzc_glb_swrst_s19_lock + 25 + 25 + + + tzc_glb_swrst_s18_lock + 24 + 24 + + + tzc_glb_swrst_s17_lock + 23 + 23 + + + tzc_glb_swrst_s16_lock + 22 + 22 + + + tzc_glb_swrst_s15_lock + 21 + 21 + + + tzc_glb_swrst_s14_lock + 20 + 20 + + + tzc_glb_swrst_s13_lock + 19 + 19 + + + tzc_glb_swrst_s12_lock + 18 + 18 + + + tzc_glb_swrst_s11_lock + 17 + 17 + + + tzc_glb_swrst_s10_lock + 16 + 16 + + + tzc_glb_swrst_s2f_lock + 15 + 15 + + + tzc_glb_swrst_s2e_lock + 14 + 14 + + + tzc_glb_swrst_s2d_lock + 13 + 13 + + + tzc_glb_swrst_s2c_lock + 12 + 12 + + + tzc_glb_swrst_s2b_lock + 11 + 11 + + + tzc_glb_swrst_s2a_lock + 10 + 10 + + + tzc_glb_swrst_s29_lock + 9 + 9 + + + tzc_glb_swrst_s28_lock + 8 + 8 + + + tzc_glb_swrst_s27_lock + 7 + 7 + + + tzc_glb_swrst_s26_lock + 6 + 6 + + + tzc_glb_swrst_s25_lock + 5 + 5 + + + tzc_glb_swrst_s24_lock + 4 + 4 + + + tzc_glb_swrst_s23_lock + 3 + 3 + + + tzc_glb_swrst_s22_lock + 2 + 2 + + + tzc_glb_swrst_s21_lock + 1 + 1 + + + tzc_glb_swrst_s20_lock + 0 + 0 + + + + + tzc_glb_ctrl_2 + tzc_glb_ctrl_2. + 0xF08 + + + tzc_glb_gpio_28_lock + 28 + 28 + + + tzc_glb_gpio_27_lock + 27 + 27 + + + tzc_glb_gpio_26_lock + 26 + 26 + + + tzc_glb_gpio_25_lock + 25 + 25 + + + tzc_glb_gpio_24_lock + 24 + 24 + + + tzc_glb_gpio_23_lock + 23 + 23 + + + tzc_glb_gpio_22_lock + 22 + 22 + + + tzc_glb_gpio_21_lock + 21 + 21 + + + tzc_glb_gpio_20_lock + 20 + 20 + + + tzc_glb_gpio_19_lock + 19 + 19 + + + tzc_glb_gpio_18_lock + 18 + 18 + + + tzc_glb_gpio_17_lock + 17 + 17 + + + tzc_glb_gpio_16_lock + 16 + 16 + + + tzc_glb_gpio_15_lock + 15 + 15 + + + tzc_glb_gpio_14_lock + 14 + 14 + + + tzc_glb_gpio_13_lock + 13 + 13 + + + tzc_glb_gpio_12_lock + 12 + 12 + + + tzc_glb_gpio_11_lock + 11 + 11 + + + tzc_glb_gpio_10_lock + 10 + 10 + + + tzc_glb_gpio_9_lock + 9 + 9 + + + tzc_glb_gpio_8_lock + 8 + 8 + + + tzc_glb_gpio_7_lock + 7 + 7 + + + tzc_glb_gpio_6_lock + 6 + 6 + + + tzc_glb_gpio_5_lock + 5 + 5 + + + tzc_glb_gpio_4_lock + 4 + 4 + + + tzc_glb_gpio_3_lock + 3 + 3 + + + tzc_glb_gpio_2_lock + 2 + 2 + + + tzc_glb_gpio_1_lock + 1 + 1 + + + tzc_glb_gpio_0_lock + 0 + 0 + + + + + tzc_glb_ctrl_3 + tzc_glb_ctrl_3. + 0xF0C + + + + + + rf + rf. + 0x40001000 + rf + 32 + read-write + + 0 + 0x1000 + registers + + + + rf_rev + Silicon revision + 0x0 + + + hw_rev + 16 + 23 + + + fw_rev + 8 + 15 + + + rf_id + 0 + 7 + + + + + rf_fsm_ctrl_hw + Digital Control + 0x4 + + + rf_rc_state_value + 28 + 30 + + + rf_fsm_st_int_set + 24 + 24 + + + rf_fsm_st_int_clr + 20 + 20 + + + rf_fsm_st_int + 16 + 16 + + + rf_fsm_st_int_sel + 12 + 14 + + + rf_rc_state_dbg_en + 11 + 11 + + + rf_rc_state_dbg + 8 + 10 + + + rf_fsm_state + 4 + 6 + + + rf_fsm_t2r_cal_mode + 2 + 3 + + + rf_fsm_ctrl_en + 1 + 1 + + + + + rf_fsm_ctrl_sw + rfsm status reg + 0x8 + + + lo_unlocked + 20 + 20 + + + inc_cal_timeout + 16 + 16 + + + full_cal_en + 12 + 12 + + + rf_fsm_sw_st_vld + 8 + 8 + + + rf_fsm_sw_st + 0 + 4 + + + + + rfctrl_hw_en + Control logic switch + 0xC + + + adda_ctrl_hw + 12 + 12 + + + rbb_pkdet_out_rstn_ctrl_hw + 11 + 11 + + + rbb_pkdet_en_ctrl_hw + 10 + 10 + + + sdm_ctrl_hw + 9 + 9 + + + inc_fcal_ctrl_en_hw + 8 + 8 + + + inc_acal_ctrl_en_hw + 7 + 7 + + + lo_ctrl_hw + 6 + 6 + + + trxcal_ctrl_hw + 5 + 5 + + + rbb_bw_ctrl_hw + 4 + 4 + + + lna_ctrl_hw + 3 + 3 + + + tx_gain_ctrl_hw + 2 + 2 + + + rx_gain_ctrl_hw + 1 + 1 + + + pu_ctrl_hw + 0 + 0 + + + + + temp_comp + temp_comp. + 0x10 + + + temp_comp_en + 16 + 16 + + + const_fcal + 8 + 15 + + + const_acal + 0 + 7 + + + + + rfcal_status + rfcal_status. + 0x14 + + + dpd_status + 30 + 31 + + + tenscal_status + 28 + 29 + + + pwdet_cal_status + 26 + 27 + + + riqcal_status_resv + 24 + 25 + + + tiqcal_status_resv + 22 + 23 + + + lo_leakcal_status + 20 + 21 + + + rccal_status + 18 + 19 + + + tos_status + 16 + 17 + + + ros_status + 14 + 15 + + + clkpll_cal_status + 12 + 13 + + + inc_acal_status + 10 + 11 + + + inc_fcal_status + 8 + 9 + + + acal_status + 6 + 7 + + + fcal_status + 4 + 5 + + + adc_oscal_status + 2 + 3 + + + rcal_status + 0 + 1 + + + + + rfcal_status2 + rfcal_status2. + 0x18 + + + dl_rfcal_table_status + 0 + 1 + + + + + rfcal_ctrlen + Calibration mode register + 0x1C + + + dpd_en + 17 + 17 + + + tsencal_en + 16 + 16 + + + pwdet_cal_en + 15 + 15 + + + riqcal_en + 14 + 14 + + + tiqcal_en + 13 + 13 + + + lo_leakcal_en + 12 + 12 + + + rccal_en + 11 + 11 + + + toscal_en + 10 + 10 + + + roscal_en + 9 + 9 + + + clkpll_cal_en + 8 + 8 + + + roscal_inc_en + 7 + 7 + + + acal_inc_en + 6 + 6 + + + fcal_inc_en + 5 + 5 + + + acal_en + 4 + 4 + + + fcal_en + 3 + 3 + + + dl_rfcal_table_en + 2 + 2 + + + adc_oscal_en + 1 + 1 + + + rcal_en_resv + 0 + 0 + + + + + rfcal_stateen + rf calibration state enabl in full cal list + 0x20 + + + rfcal_level + 30 + 31 + + + dpd_sten + 16 + 16 + + + tsencal_sten + 15 + 15 + + + pwdet_cal_sten + 14 + 14 + + + riqcal_sten + 13 + 13 + + + tiqcal_sten + 12 + 12 + + + lo_leakcal_sten + 11 + 11 + + + rccal_sten + 10 + 10 + + + toscal_sten_resv + 9 + 9 + + + roscal_sten + 8 + 8 + + + clkpll_cal_sten + 7 + 7 + + + inc_acal_sten + 6 + 6 + + + inc_fcal_sten + 5 + 5 + + + acal_sten + 4 + 4 + + + fcal_sten + 3 + 3 + + + dl_rfcal_table_sten + 2 + 2 + + + adc_oscal_sten + 1 + 1 + + + rcal_sten_resv + 0 + 0 + + + + + saradc_resv + SARADC Control Registers + 0x24 + + + + rf_base_ctrl1 + ZRF Control register 0 + 0x28 + + + mbg_trim + 27 + 28 + + + pud_pa_dly + 14 + 15 + + + pud_iref_dly + 12 + 13 + + + pud_vco_dly + 10 + 11 + + + ppu_lead + 8 + 9 + + + lo_sdm_rst_dly + 2 + 3 + + + aupll_sdm_rst_dly + 0 + 1 + + + + + rf_base_ctrl2 + ZRF Control register 0 + 0x2C + + + + pucr1 + pucr1. + 0x30 + + + pu_tosdac + 31 + 31 + + + pu_pwrmx + 30 + 30 + + + pu_rosdac + 29 + 29 + + + pu_pkdet + 28 + 28 + + + trsw_en + 26 + 26 + + + pu_txbuf + 25 + 25 + + + pu_rxbuf + 24 + 24 + + + pu_osmx + 23 + 23 + + + pu_pfd + 22 + 22 + + + pu_fbdv + 21 + 21 + + + pu_vco + 20 + 20 + + + pu_dac + 19 + 19 + + + pu_tbb + 18 + 18 + + + pu_tmx + 17 + 17 + + + pu_pa + 16 + 16 + + + pu_op_atest + 15 + 15 + + + pu_adc + 14 + 14 + + + adc_clk_en + 13 + 13 + + + pu_adda_ldo + 12 + 12 + + + pu_rbb + 11 + 11 + + + pu_rmx + 10 + 10 + + + pu_rmxgm + 9 + 9 + + + pu_lna + 8 + 8 + + + pu_sfreg + 0 + 0 + + + + + pucr1_hw + read only from hardware logic + 0x34 + + + pu_tosdac_hw + 31 + 31 + + + pu_rosdac_hw + 29 + 29 + + + pu_pkdet_hw + 28 + 28 + + + trsw_en_hw + 26 + 26 + + + pu_txbuf_hw + 25 + 25 + + + pu_rxbuf_hw + 24 + 24 + + + pu_osmx_hw + 23 + 23 + + + pu_pfd_hw + 22 + 22 + + + pu_fbdv_hw + 21 + 21 + + + pu_vco_hw + 20 + 20 + + + pu_dac_hw + 19 + 19 + + + pu_tbb_hw + 18 + 18 + + + pu_tmx_hw + 17 + 17 + + + pu_pa_hw + 16 + 16 + + + pu_adc_hw + 14 + 14 + + + adc_clk_en_hw + 13 + 13 + + + pu_adda_ldo_hw + 12 + 12 + + + pu_rbb_hw + 11 + 11 + + + pu_rmx_hw + 10 + 10 + + + pu_rmxgm_hw + 9 + 9 + + + pu_lna_hw + 8 + 8 + + + pu_sfreg_hw + 0 + 0 + + + + + pucr2 + pucr2. + 0x38 + + + + pucr2_hw + pucr2_hw. + 0x3C + + + + ppu_ctrl_hw + ppu_ctrl_hw. + 0x40 + + + ppu_txbuf_hw + 25 + 25 + + + ppu_rxbuf_hw + 24 + 24 + + + ppu_osmx_hw + 23 + 23 + + + ppu_pfd_hw + 22 + 22 + + + ppu_fbdv_hw + 21 + 21 + + + ppu_vco_hw + 20 + 20 + + + ppu_rbb_hw + 11 + 11 + + + ppu_rmxgm_hw + 9 + 9 + + + ppu_lna_hw + 8 + 8 + + + + + pud_ctrl_hw + pud_ctrl_hw. + 0x44 + + + pud_vco_hw + 20 + 20 + + + + + trx_gain1 + gain control1 + 0x48 + + + gc_tbb_boost + 28 + 29 + + + gc_tbb + 20 + 24 + + + gc_tmx + 16 + 18 + + + gc_rbb2 + 12 + 14 + + + gc_rbb1 + 8 + 9 + + + gc_rmxgm + 4 + 5 + + + gc_lna + 0 + 2 + + + + + trx_gain_hw + trx gain hardware readback + 0x4C + + + gc_tbb_boost_hw + 28 + 29 + + + gc_tbb_hw + 20 + 24 + + + gc_tmx_hw + 16 + 18 + + + gc_rbb2_hw + 12 + 14 + + + gc_rbb1_hw + 8 + 9 + + + gc_rmxgm_hw + 4 + 5 + + + gc_lna_hw + 0 + 2 + + + + + ten_dc + dc test register + 0x50 + + + ten_lodist + 27 + 27 + + + ten_lf + 26 + 26 + + + ten_pfdcp + 25 + 25 + + + ten_vco + 24 + 24 + + + ten_dac_q + 22 + 22 + + + ten_dac_i + 21 + 21 + + + ten_adc + 20 + 20 + + + ten_tbb + 19 + 19 + + + ten_atest + 18 + 18 + + + ten_bq + 17 + 17 + + + ten_tia + 16 + 16 + + + ten_tmx + 15 + 15 + + + ten_pa + 14 + 14 + + + ten_rrf_1 + 13 + 13 + + + ten_rrf_0 + 12 + 12 + + + ten_clkpll_sfreg + 9 + 9 + + + ten_clkpll + 8 + 8 + + + dc_tp_clkpll_en + 4 + 4 + + + dc_tp_en + 3 + 3 + + + tmux + 0 + 2 + + + + + ten_dig + digital test register + 0x54 + + + rf_dtest_en + 23 + 23 + + + dtest_pull_down + 9 + 9 + + + dten_lo_fref + 8 + 8 + + + dten_lo_fsdm + 6 + 6 + + + dten_clkpll_fin + 5 + 5 + + + dten_clkpll_fref + 4 + 4 + + + dten_clkpll_fsdm + 3 + 3 + + + dten_clkpll_clk32m + 2 + 2 + + + dten_clkpll_clk96m + 1 + 1 + + + dten_clkpll_postdiv_clk + 0 + 0 + + + + + ten_ac + ac test register + 0x58 + + + atest_in_en_i + 23 + 23 + + + atest_in_en_q + 22 + 22 + + + atest_out_en_i + 21 + 21 + + + atest_out_en_q + 20 + 20 + + + atest_gain_r5 + 16 + 18 + + + atest_gain_r6 + 14 + 15 + + + atest_gain_r7 + 12 + 13 + + + atest_gain_r8 + 10 + 11 + + + atest_gain_r9 + 8 + 9 + + + atest_in_en + 6 + 6 + + + atest_in_trx_sw + 5 + 5 + + + atest_dac_en + 4 + 4 + + + atest_op_cc + 0 + 3 + + + + + pmip_mv2aon + pmip_mv2aon. + 0x5C + + + + cip + RX normal bias mode registers + 0x60 + + + vg13_sel + 2 + 3 + + + vg11_sel + 0 + 1 + + + + + pa1 + pa1. + 0x64 + + + pa_att_gc + 28 + 31 + + + pa_pwrmx_bm + 24 + 26 + + + pa_pwrmx_dac_pn_switch + 22 + 22 + + + pa_pwrmx_osdac + 18 + 21 + + + pa_lz_bias_en + 17 + 17 + + + pa_ib_fix + 16 + 16 + + + pa_half_on + 15 + 15 + + + pa_vbcas + 12 + 14 + + + pa_vbcore + 8 + 11 + + + pa_iet + 4 + 7 + + + pa_etb_en + 3 + 3 + + + pa_iaq + 0 + 2 + + + + + pa2 + RX normal bias mode registers + 0x68 + + + pa_ib_fix_hw + 17 + 17 + + + pa_half_on_hw + 16 + 16 + + + pa_vbcas_hw + 12 + 14 + + + pa_vbcore_hw + 8 + 11 + + + pa_iet_hw + 4 + 7 + + + pa_etb_en_hw + 3 + 3 + + + + + tmx + tmx. + 0x6C + + + tx_tsense_en + 16 + 16 + + + tmx_bm_cas_bulk + 12 + 14 + + + tmx_bm_cas + 8 + 10 + + + tmx_bm_sw + 4 + 6 + + + tmx_cs + 0 + 2 + + + + + tbb + tbb. + 0x70 + + + tbb_tosdac_i + 24 + 29 + + + tbb_tosdac_q + 16 + 21 + + + tbb_atest_out_en + 15 + 15 + + + tbb_iq_bias_short + 14 + 14 + + + tbb_cflt + 12 + 13 + + + tbb_vcm + 8 + 9 + + + tbb_bm_cg + 4 + 5 + + + tbb_bm_sf + 0 + 1 + + + + + lna + lna. + 0x74 + + + lna_lg_gsel + 24 + 26 + + + lna_cap_lg + 20 + 21 + + + lna_rfb_match + 16 + 18 + + + lna_load_csw_hw + 12 + 15 + + + lna_load_csw + 8 + 11 + + + lna_bm_hw + 4 + 7 + + + lna_bm + 0 + 3 + + + + + rmxgm + rmxgm. + 0x78 + + + rmxgm_10m_mode_en + 8 + 8 + + + rmxgm_bm + 4 + 6 + + + rmx_bm + 0 + 2 + + + + + rbb1 + rbb1. + 0x7C + + + rosdac_range + 31 + 31 + + + rosdac_i_hw + 24 + 29 + + + rosdac_q_hw + 16 + 21 + + + rosdac_i + 8 + 13 + + + rosdac_q + 0 + 5 + + + + + rbb2 + rbb2. + 0x80 + + + rbb_cap1_fc_i + 24 + 29 + + + rbb_cap1_fc_q + 16 + 21 + + + rbb_cap2_fc_i + 8 + 13 + + + rbb_cap2_fc_q + 0 + 5 + + + + + rbb3 + rbb3. + 0x84 + + + pwr_det_en + 31 + 31 + + + rxiqcal_en + 28 + 28 + + + rbb_bw + 24 + 25 + + + rbb_tia_iqbias_short + 21 + 21 + + + rbb_bq_iqbias_short + 20 + 20 + + + rbb_vcm + 16 + 17 + + + rbb_bm_op + 12 + 14 + + + rbb_deq + 8 + 9 + + + rbb_bt_fif_tune + 5 + 6 + + + rbb_bt_mode + 4 + 4 + + + rbb_bt_mode_hw + 0 + 0 + + + + + rbb4 + rbb4. + 0x88 + + + pkdet_out_latch + 24 + 24 + + + pkdet_out_raw + 20 + 20 + + + rbb_pkdet_en_hw + 16 + 16 + + + rbb_pkdet_out_rstn_hw + 12 + 12 + + + rbb_pkdet_en + 8 + 8 + + + rbb_pkdet_out_rstn + 4 + 4 + + + rbb_pkdet_vth + 0 + 3 + + + + + adda1 + adda1. + 0x8C + + + adda_ldo_dvdd_sel_hw + 24 + 26 + + + adda_ldo_dvdd_sel + 20 + 22 + + + adda_ldo_byps + 16 + 16 + + + dac_clk_sync_inv + 13 + 13 + + + dac_rccalsel + 12 + 12 + + + dac_clk_sel + 8 + 9 + + + dac_bias_sel + 4 + 5 + + + dac_dvdd_sel + 0 + 1 + + + + + adda2 + adda2. + 0x90 + + + adc_clk_div_sel + 28 + 28 + + + adc_clk_inv + 24 + 24 + + + adc_clk_sync_inv + 20 + 20 + + + adc_gt_rm + 16 + 16 + + + adc_sar_ascal_en + 12 + 12 + + + adc_dvdd_sel + 8 + 9 + + + adc_dly_ctl + 4 + 5 + + + adc_vref_sel + 0 + 1 + + + + + vco1 + vco1. + 0xA0 + + + lo_vco_idac_cw_hw + 24 + 28 + + + lo_vco_idac_cw + 16 + 20 + + + lo_vco_freq_cw_hw + 8 + 15 + + + lo_vco_freq_cw + 0 + 7 + + + + + vco2 + vco2. + 0xA4 + + + acal_inc_en_hw + 16 + 16 + + + acal_vco_ud + 12 + 12 + + + acal_vref_cw + 8 + 10 + + + lo_vco_short_idac_filter + 6 + 6 + + + lo_vco_short_vbias_filter + 5 + 5 + + + lo_vco_idac_boot + 4 + 4 + + + lo_vco_vbias_cw + 0 + 1 + + + + + vco3 + vco3. + 0xA8 + + + fcal_cnt_op + 16 + 31 + + + fcal_div + 0 + 15 + + + + + vco4 + vco4. + 0xAC + + + fcal_inc_vctrl_ud + 24 + 25 + + + fcal_cnt_rdy + 20 + 20 + + + fcal_inc_large_range + 16 + 16 + + + fcal_inc_en_hw + 8 + 8 + + + fcal_cnt_start + 4 + 4 + + + + + pfdcp + pfdcp. + 0xB0 + + + lo_pfd_rst_csd_hw + 29 + 29 + + + lo_pfd_rst_csd + 28 + 28 + + + lo_pfd_rvdd_boost + 24 + 24 + + + lo_cp_hiz + 20 + 20 + + + lo_cp_opamp_en + 16 + 16 + + + lo_cp_ota_en + 12 + 12 + + + lo_cp_startup_en + 8 + 8 + + + lo_cp_sel_hw + 4 + 4 + + + lo_cp_sel + 0 + 0 + + + + + lo + lo. + 0xB4 + + + lo_slipped_up + 24 + 24 + + + lo_slipped_dn + 20 + 20 + + + lo_lf_r4_short + 18 + 18 + + + lo_lf_r4 + 16 + 17 + + + lo_lf_cz + 14 + 15 + + + lo_lf_rz + 12 + 13 + + + lo_lf_cz_hw + 8 + 9 + + + lo_lf_r4_hw + 4 + 5 + + + lo_lf_rz_hw + 0 + 1 + + + + + fbdv + fbdv. + 0xB8 + + + lo_fbdv_rst_hw + 20 + 20 + + + lo_fbdv_rst + 16 + 16 + + + lo_fbdv_sel_fb_clk + 12 + 13 + + + lo_fbdv_sel_sample_clk + 8 + 9 + + + lo_fbdv_halfstep_en + 4 + 4 + + + lo_fbdv_halfstep_en_hw + 0 + 0 + + + + + lodist + lodist. + 0xBC + + + lo_lodist_rxbuf_stre + 28 + 28 + + + lo_lodist_txbuf_stre + 24 + 24 + + + lo_osmx_cap + 20 + 23 + + + lo_osmx_capbank_bias + 16 + 17 + + + lo_osmx_vbuf_stre + 12 + 12 + + + lo_osmx_fix_cap + 8 + 8 + + + lo_osmx_en_xgm + 4 + 4 + + + lo_osmx_xgm_boost + 0 + 0 + + + + + sdm1 + sdm1. + 0xC0 + + + lo_sdm_flag + 20 + 20 + + + lo_sdm_rstb_hw + 17 + 17 + + + lo_sdm_rstb + 16 + 16 + + + lo_sdm_bypass + 12 + 12 + + + lo_sdm_dither_sel + 8 + 9 + + + lo_sdm_bypass_hw + 4 + 4 + + + lo_sdm_dither_sel_hw + 0 + 1 + + + + + sdm2 + sdm2. + 0xC4 + + + lo_sdmin + 0 + 29 + + + + + sdm3 + sdm3. + 0xC8 + + + lo_sdmin_hw + 0 + 29 + + + + + rf_resv_reg_0 + rf_resv_reg_0. + 0xEC + + + rf_reserved0 + 0 + 31 + + + + + rf_resv_reg_1 + rf_resv_reg_1. + 0xF0 + + + rf_reserved1 + 0 + 31 + + + + + rf_resv_reg_2 + rf_resv_reg_2. + 0xF4 + + + rf_reserved2 + 0 + 31 + + + + + rrf_gain_index1 + rrf_gain_index1. + 0xF8 + + + gain_ctrl5_gc_lna + 27 + 29 + + + gain_ctrl5_gc_rmxgm + 25 + 26 + + + gain_ctrl4_gc_lna + 22 + 24 + + + gain_ctrl4_gc_rmxgm + 20 + 21 + + + gain_ctrl3_gc_lna + 17 + 19 + + + gain_ctrl3_gc_rmxgm + 15 + 16 + + + gain_ctrl2_gc_lna + 12 + 14 + + + gain_ctrl2_gc_rmxgm + 10 + 11 + + + gain_ctrl1_gc_lna + 7 + 9 + + + gain_ctrl1_gc_rmxgm + 5 + 6 + + + gain_ctrl0_gc_lna + 2 + 4 + + + gain_ctrl0_gc_rmxgm + 0 + 1 + + + + + rrf_gain_index2 + rrf_gain_index2. + 0xFC + + + gain_ctrl6_gc_lna + 12 + 14 + + + gain_ctrl6_gc_rmxgm + 10 + 11 + + + gain_ctrl7_gc_lna + 7 + 9 + + + gain_ctrl7_gc_rmxgm + 5 + 6 + + + gain_ctrl8_gc_lna + 2 + 4 + + + gain_ctrl8_gc_rmxgm + 0 + 1 + + + + + lna_ctrl_hw_mux + lna_ctrl_hw_mux. + 0x100 + + + lna_load_csw_lg + 12 + 15 + + + lna_load_csw_hg + 8 + 11 + + + lna_bm_lg + 4 + 7 + + + lna_bm_hg + 0 + 3 + + + + + rbb_gain_index1 + rbb_gain_index1. + 0x104 + + + gain_ctrl3_gc_rbb2 + 28 + 30 + + + gain_ctrl3_gc_rbb1 + 24 + 25 + + + gain_ctrl2_gc_rbb2 + 20 + 22 + + + gain_ctrl2_gc_rbb1 + 16 + 17 + + + gain_ctrl1_gc_rbb2 + 12 + 14 + + + gain_ctrl1_gc_rbb1 + 8 + 9 + + + gain_ctrl0_gc_rbb2 + 4 + 6 + + + gain_ctrl0_gc_rbb1 + 0 + 1 + + + + + rbb_gain_index2 + rbb_gain_index2. + 0x108 + + + gain_ctrl7_gc_rbb2 + 28 + 30 + + + gain_ctrl7_gc_rbb1 + 24 + 25 + + + gain_ctrl6_gc_rbb2 + 20 + 22 + + + gain_ctrl6_gc_rbb1 + 16 + 17 + + + gain_ctrl5_gc_rbb2 + 12 + 14 + + + gain_ctrl5_gc_rbb1 + 8 + 9 + + + gain_ctrl4_gc_rbb2 + 4 + 6 + + + gain_ctrl4_gc_rbb1 + 0 + 1 + + + + + rbb_gain_index3 + rbb_gain_index3. + 0x10C + + + gain_ctrl11_gc_rbb2 + 28 + 30 + + + gain_ctrl11_gc_rbb1 + 24 + 25 + + + gain_ctrl10_gc_rbb2 + 20 + 22 + + + gain_ctrl10_gc_rbb1 + 16 + 17 + + + gain_ctrl9_gc_rbb2 + 12 + 14 + + + gain_ctrl9_gc_rbb1 + 8 + 9 + + + gain_ctrl8_gc_rbb2 + 4 + 6 + + + gain_ctrl8_gc_rbb1 + 0 + 1 + + + + + rbb_gain_index4 + rbb_gain_index4. + 0x110 + + + gain_ctrl15_gc_rbb2 + 28 + 30 + + + gain_ctrl15_gc_rbb1 + 24 + 25 + + + gain_ctrl14_gc_rbb2 + 20 + 22 + + + gain_ctrl14_gc_rbb1 + 16 + 17 + + + gain_ctrl13_gc_rbb2 + 12 + 14 + + + gain_ctrl13_gc_rbb1 + 8 + 9 + + + gain_ctrl12_gc_rbb2 + 4 + 6 + + + gain_ctrl12_gc_rbb1 + 0 + 1 + + + + + rbb_gain_index5 + rbb_gain_index5. + 0x114 + + + gain_ctrl16_gc_rbb2 + 4 + 6 + + + gain_ctrl16_gc_rbb1 + 0 + 1 + + + + + tbb_gain_index1 + tbb_gain_index1. + 0x118 + + + gain_ctrl1_gc_tbb_boost + 30 + 31 + + + gain_ctrl1_dac_bias_sel + 28 + 29 + + + gain_ctrl1_gc_tmx + 24 + 26 + + + gain_ctrl1_gc_tbb + 16 + 20 + + + gain_ctrl0_gc_tbb_boost + 14 + 15 + + + gain_ctrl0_dac_bias_sel + 12 + 13 + + + gain_ctrl0_gc_tmx + 8 + 10 + + + gain_ctrl0_gc_tbb + 0 + 4 + + + + + tbb_gain_index2 + tbb_gain_index2. + 0x11C + + + gain_ctrl3_gc_tbb_boost + 30 + 31 + + + gain_ctrl3_dac_bias_sel + 28 + 29 + + + gain_ctrl3_gc_tmx + 24 + 26 + + + gain_ctrl3_gc_tbb + 16 + 20 + + + gain_ctrl2_gc_tbb_boost + 14 + 15 + + + gain_ctrl2_dac_bias_sel + 12 + 13 + + + gain_ctrl2_gc_tmx + 8 + 10 + + + gain_ctrl2_gc_tbb + 0 + 4 + + + + + tbb_gain_index3 + tbb_gain_index3. + 0x120 + + + gain_ctrl5_gc_tbb_boost + 30 + 31 + + + gain_ctrl5_dac_bias_sel + 28 + 29 + + + gain_ctrl5_gc_tmx + 24 + 26 + + + gain_ctrl5_gc_tbb + 16 + 20 + + + gain_ctrl4_gc_tbb_boost + 14 + 15 + + + gain_ctrl4_dac_bias_sel + 12 + 13 + + + gain_ctrl4_gc_tmx + 8 + 10 + + + gain_ctrl4_gc_tbb + 0 + 4 + + + + + tbb_gain_index4 + tbb_gain_index4. + 0x124 + + + gain_ctrl7_gc_tbb_boost + 30 + 31 + + + gain_ctrl7_dac_bias_sel + 28 + 29 + + + gain_ctrl7_gc_tmx + 24 + 26 + + + gain_ctrl7_gc_tbb + 16 + 20 + + + gain_ctrl6_gc_tbb_boost + 14 + 15 + + + gain_ctrl6_dac_bias_sel + 12 + 13 + + + gain_ctrl6_gc_tmx + 8 + 10 + + + gain_ctrl6_gc_tbb + 0 + 4 + + + + + pa_reg_ctrl_hw1 + pa_reg_ctrl_hw1. + 0x128 + + + pa_vbcas_11n + 20 + 22 + + + pa_vbcore_11n + 16 + 19 + + + pa_iet_11n + 12 + 15 + + + + + pa_reg_ctrl_hw2 + pa_reg_ctrl_hw2. + 0x12C + + + pa_vbcas_11b + 20 + 22 + + + pa_vbcore_11b + 16 + 19 + + + pa_iet_11b + 12 + 15 + + + pa_vbcas_11g + 8 + 10 + + + pa_vbcore_11g + 4 + 7 + + + pa_iet_11g + 0 + 3 + + + + + pa_reg_wifi_ctrl_hw + pa_reg_wifi_ctrl_hw. + 0x130 + + + pa_ib_fix_wifi + 16 + 16 + + + pa_etb_en_wifi + 8 + 8 + + + pa_half_on_wifi + 0 + 0 + + + + + adda_reg_ctrl_hw + adda_reg_ctrl_hw. + 0x134 + + + adda_ldo_dvdd_sel_tx + 4 + 6 + + + adda_ldo_dvdd_sel_rx + 0 + 2 + + + + + lo_reg_ctrl_hw1 + lo_reg_ctrl_hw1. + 0x138 + + + lo_lf_r4_tx + 24 + 25 + + + lo_lf_r4_rx + 20 + 21 + + + lo_lf_rz_tx + 16 + 17 + + + lo_lf_rz_rx + 12 + 13 + + + lo_lf_cz_tx + 8 + 9 + + + lo_lf_cz_rx + 4 + 5 + + + lo_cp_sel_tx + 3 + 3 + + + lo_cp_sel_rx + 2 + 2 + + + lo_fbdv_halfstep_en_tx + 1 + 1 + + + lo_fbdv_halfstep_en_rx + 0 + 0 + + + + + lo_cal_ctrl_hw1 + lo_cal_ctrl_hw1. + 0x13C + + + lo_vco_freq_cw_2408 + 24 + 31 + + + lo_vco_idac_cw_2408 + 16 + 20 + + + lo_vco_freq_cw_2404 + 8 + 15 + + + lo_vco_idac_cw_2404 + 0 + 4 + + + + + lo_cal_ctrl_hw2 + lo_cal_ctrl_hw2. + 0x140 + + + lo_vco_freq_cw_2416 + 24 + 31 + + + lo_vco_idac_cw_2416 + 16 + 20 + + + lo_vco_freq_cw_2412 + 8 + 15 + + + lo_vco_idac_cw_2412 + 0 + 4 + + + + + lo_cal_ctrl_hw3 + lo_cal_ctrl_hw3. + 0x144 + + + lo_vco_freq_cw_2424 + 24 + 31 + + + lo_vco_idac_cw_2424 + 16 + 20 + + + lo_vco_freq_cw_2420 + 8 + 15 + + + lo_vco_idac_cw_2420 + 0 + 4 + + + + + lo_cal_ctrl_hw4 + lo_cal_ctrl_hw4. + 0x148 + + + lo_vco_freq_cw_2432 + 24 + 31 + + + lo_vco_idac_cw_2432 + 16 + 20 + + + lo_vco_freq_cw_2428 + 8 + 15 + + + lo_vco_idac_cw_2428 + 0 + 4 + + + + + lo_cal_ctrl_hw5 + lo_cal_ctrl_hw5. + 0x14C + + + lo_vco_freq_cw_2440 + 24 + 31 + + + lo_vco_idac_cw_2440 + 16 + 20 + + + lo_vco_freq_cw_2436 + 8 + 15 + + + lo_vco_idac_cw_2436 + 0 + 4 + + + + + lo_cal_ctrl_hw6 + lo_cal_ctrl_hw6. + 0x150 + + + lo_vco_freq_cw_2448 + 24 + 31 + + + lo_vco_idac_cw_2448 + 16 + 20 + + + lo_vco_freq_cw_2444 + 8 + 15 + + + lo_vco_idac_cw_2444 + 0 + 4 + + + + + lo_cal_ctrl_hw7 + lo_cal_ctrl_hw7. + 0x154 + + + lo_vco_freq_cw_2456 + 24 + 31 + + + lo_vco_idac_cw_2456 + 16 + 20 + + + lo_vco_freq_cw_2452 + 8 + 15 + + + lo_vco_idac_cw_2452 + 0 + 4 + + + + + lo_cal_ctrl_hw8 + lo_cal_ctrl_hw8. + 0x158 + + + lo_vco_freq_cw_2464 + 24 + 31 + + + lo_vco_idac_cw_2464 + 16 + 20 + + + lo_vco_freq_cw_2460 + 8 + 15 + + + lo_vco_idac_cw_2460 + 0 + 4 + + + + + lo_cal_ctrl_hw9 + lo_cal_ctrl_hw9. + 0x15C + + + lo_vco_freq_cw_2472 + 24 + 31 + + + lo_vco_idac_cw_2472 + 16 + 20 + + + lo_vco_freq_cw_2468 + 8 + 15 + + + lo_vco_idac_cw_2468 + 0 + 4 + + + + + lo_cal_ctrl_hw10 + lo_cal_ctrl_hw10. + 0x160 + + + lo_vco_freq_cw_2480 + 24 + 31 + + + lo_vco_idac_cw_2480 + 16 + 20 + + + lo_vco_freq_cw_2476 + 8 + 15 + + + lo_vco_idac_cw_2476 + 0 + 4 + + + + + lo_cal_ctrl_hw11 + lo_cal_ctrl_hw11. + 0x164 + + + lo_vco_freq_cw_2484 + 8 + 15 + + + lo_vco_idac_cw_2484 + 0 + 4 + + + + + rosdac_ctrl_hw1 + rosdac_ctrl_hw1. + 0x168 + + + rosdac_q_gc1 + 24 + 29 + + + rosdac_i_gc1 + 16 + 21 + + + rosdac_q_gc0 + 8 + 13 + + + rosdac_i_gc0 + 0 + 5 + + + + + rosdac_ctrl_hw2 + rosdac_ctrl_hw2. + 0x16C + + + rosdac_q_gc3 + 24 + 29 + + + rosdac_i_gc3 + 16 + 21 + + + rosdac_q_gc2 + 8 + 13 + + + rosdac_i_gc2 + 0 + 5 + + + + + rxiq_ctrl_hw1 + rxiq_ctrl_hw1. + 0x170 + + + rx_iq_gain_comp_gc0 + 16 + 26 + + + rx_iq_phase_comp_gc0 + 0 + 9 + + + + + rxiq_ctrl_hw2 + rxiq_ctrl_hw2. + 0x174 + + + rx_iq_gain_comp_gc1 + 16 + 26 + + + rx_iq_phase_comp_gc1 + 0 + 9 + + + + + rxiq_ctrl_hw3 + rxiq_ctrl_hw3. + 0x178 + + + rx_iq_gain_comp_gc2 + 16 + 26 + + + rx_iq_phase_comp_gc2 + 0 + 9 + + + + + rxiq_ctrl_hw4 + rxiq_ctrl_hw4. + 0x17C + + + rx_iq_gain_comp_gc3 + 16 + 26 + + + rx_iq_phase_comp_gc3 + 0 + 9 + + + + + tosdac_ctrl_hw1 + tosdac_ctrl_hw1. + 0x180 + + + tbb_tosdac_q_gc1 + 24 + 29 + + + tbb_tosdac_i_gc1 + 16 + 21 + + + tbb_tosdac_q_gc0 + 8 + 13 + + + tbb_tosdac_i_gc0 + 0 + 5 + + + + + tosdac_ctrl_hw2 + tosdac_ctrl_hw2. + 0x184 + + + tbb_tosdac_q_gc3 + 24 + 29 + + + tbb_tosdac_i_gc3 + 16 + 21 + + + tbb_tosdac_q_gc2 + 8 + 13 + + + tbb_tosdac_i_gc2 + 0 + 5 + + + + + tosdac_ctrl_hw3 + tosdac_ctrl_hw3. + 0x188 + + + tbb_tosdac_q_gc5 + 24 + 29 + + + tbb_tosdac_i_gc5 + 16 + 21 + + + tbb_tosdac_q_gc4 + 8 + 13 + + + tbb_tosdac_i_gc4 + 0 + 5 + + + + + tosdac_ctrl_hw4 + tosdac_ctrl_hw4. + 0x18C + + + tbb_tosdac_q_gc7 + 24 + 29 + + + tbb_tosdac_i_gc7 + 16 + 21 + + + tbb_tosdac_q_gc6 + 8 + 13 + + + tbb_tosdac_i_gc6 + 0 + 5 + + + + + tx_iq_gain_hw0 + tx_iq_gain_hw0. + 0x190 + + + tx_iq_gain_comp_gc0 + 16 + 26 + + + tx_iq_phase_comp_gc0 + 0 + 9 + + + + + tx_iq_gain_hw1 + tx_iq_gain_hw1. + 0x194 + + + tx_iq_gain_comp_gc1 + 16 + 26 + + + tx_iq_phase_comp_gc1 + 0 + 9 + + + + + tx_iq_gain_hw2 + tx_iq_gain_hw2. + 0x198 + + + tx_iq_gain_comp_gc2 + 16 + 26 + + + tx_iq_phase_comp_gc2 + 0 + 9 + + + + + tx_iq_gain_hw3 + tx_iq_gain_hw3. + 0x19C + + + tx_iq_gain_comp_gc3 + 16 + 26 + + + tx_iq_phase_comp_gc3 + 0 + 9 + + + + + tx_iq_gain_hw4 + tx_iq_gain_hw4. + 0x1A0 + + + tx_iq_gain_comp_gc4 + 16 + 26 + + + tx_iq_phase_comp_gc4 + 0 + 9 + + + + + tx_iq_gain_hw5 + tx_iq_gain_hw5. + 0x1A4 + + + tx_iq_gain_comp_gc5 + 16 + 26 + + + tx_iq_phase_comp_gc5 + 0 + 9 + + + + + tx_iq_gain_hw6 + tx_iq_gain_hw6. + 0x1A8 + + + tx_iq_gain_comp_gc6 + 16 + 26 + + + tx_iq_phase_comp_gc6 + 0 + 9 + + + + + tx_iq_gain_hw7 + tx_iq_gain_hw7. + 0x1AC + + + tx_iq_gain_comp_gc7 + 16 + 26 + + + tx_iq_phase_comp_gc7 + 0 + 9 + + + + + lo_sdm_ctrl_hw1 + lo_sdm_ctrl_hw1. + 0x1B0 + + + lo_sdm_dither_sel_wlan_2484 + 26 + 27 + + + lo_sdm_dither_sel_wlan_2472 + 24 + 25 + + + lo_sdm_dither_sel_wlan_2467 + 22 + 23 + + + lo_sdm_dither_sel_wlan_2462 + 20 + 21 + + + lo_sdm_dither_sel_wlan_2457 + 18 + 19 + + + lo_sdm_dither_sel_wlan_2452 + 16 + 17 + + + lo_sdm_dither_sel_wlan_2447 + 14 + 15 + + + lo_sdm_dither_sel_wlan_2442 + 12 + 13 + + + lo_sdm_dither_sel_wlan_2437 + 10 + 11 + + + lo_sdm_dither_sel_wlan_2432 + 8 + 9 + + + lo_sdm_dither_sel_wlan_2427 + 6 + 7 + + + lo_sdm_dither_sel_wlan_2422 + 4 + 5 + + + lo_sdm_dither_sel_wlan_2417 + 2 + 3 + + + lo_sdm_dither_sel_wlan_2412 + 0 + 1 + + + + + lo_sdm_ctrl_hw2 + lo_sdm_ctrl_hw2. + 0x1B4 + + + lo_sdm_dither_sel_ble_2432 + 30 + 31 + + + lo_sdm_dither_sel_ble_2430 + 28 + 29 + + + lo_sdm_dither_sel_ble_2428 + 26 + 27 + + + lo_sdm_dither_sel_ble_2426 + 24 + 25 + + + lo_sdm_dither_sel_ble_2424 + 22 + 23 + + + lo_sdm_dither_sel_ble_2422 + 20 + 21 + + + lo_sdm_dither_sel_ble_2420 + 18 + 19 + + + lo_sdm_dither_sel_ble_2418 + 16 + 17 + + + lo_sdm_dither_sel_ble_2416 + 14 + 15 + + + lo_sdm_dither_sel_ble_2414 + 12 + 13 + + + lo_sdm_dither_sel_ble_2412 + 10 + 11 + + + lo_sdm_dither_sel_ble_2410 + 8 + 9 + + + lo_sdm_dither_sel_ble_2408 + 6 + 7 + + + lo_sdm_dither_sel_ble_2406 + 4 + 5 + + + lo_sdm_dither_sel_ble_2404 + 2 + 3 + + + lo_sdm_dither_sel_ble_2402 + 0 + 1 + + + + + lo_sdm_ctrl_hw3 + lo_sdm_ctrl_hw3. + 0x1B8 + + + lo_sdm_dither_sel_ble_2464 + 30 + 31 + + + lo_sdm_dither_sel_ble_2462 + 28 + 29 + + + lo_sdm_dither_sel_ble_2460 + 26 + 27 + + + lo_sdm_dither_sel_ble_2458 + 24 + 25 + + + lo_sdm_dither_sel_ble_2456 + 22 + 23 + + + lo_sdm_dither_sel_ble_2454 + 20 + 21 + + + lo_sdm_dither_sel_ble_2452 + 18 + 19 + + + lo_sdm_dither_sel_ble_2450 + 16 + 17 + + + lo_sdm_dither_sel_ble_2448 + 14 + 15 + + + lo_sdm_dither_sel_ble_2446 + 12 + 13 + + + lo_sdm_dither_sel_ble_2444 + 10 + 11 + + + lo_sdm_dither_sel_ble_2442 + 8 + 9 + + + lo_sdm_dither_sel_ble_2440 + 6 + 7 + + + lo_sdm_dither_sel_ble_2438 + 4 + 5 + + + lo_sdm_dither_sel_ble_2436 + 2 + 3 + + + lo_sdm_dither_sel_ble_2434 + 0 + 1 + + + + + lo_sdm_ctrl_hw4 + lo_sdm_ctrl_hw4. + 0x1BC + + + lo_sdm_dither_sel_ble_tx + 16 + 17 + + + lo_sdm_dither_sel_ble_2480 + 14 + 15 + + + lo_sdm_dither_sel_ble_2478 + 12 + 13 + + + lo_sdm_dither_sel_ble_2476 + 10 + 11 + + + lo_sdm_dither_sel_ble_2474 + 8 + 9 + + + lo_sdm_dither_sel_ble_2472 + 6 + 7 + + + lo_sdm_dither_sel_ble_2470 + 4 + 5 + + + lo_sdm_dither_sel_ble_2468 + 2 + 3 + + + lo_sdm_dither_sel_ble_2466 + 0 + 1 + + + + + lo_sdm_ctrl_hw5 + lo_sdm_ctrl_hw5. + 0x1C0 + + + lo_sdm_bypass_mode + 12 + 17 + + + lo_center_freq_mhz + 0 + 11 + + + + + lo_sdm_ctrl_hw6 + lo_sdm_ctrl_hw6. + 0x1C4 + + + lo_sdmin_center + 0 + 28 + + + + + lo_sdm_ctrl_hw7 + lo_sdm_ctrl_hw7. + 0x1C8 + + + lo_sdmin_1m + 0 + 19 + + + + + lo_sdm_ctrl_hw8 + lo_sdm_ctrl_hw8. + 0x1CC + + + lo_sdmin_if + 0 + 19 + + + + + rbb_bw_ctrl_hw + rbb_bw_ctrl_hw. + 0x1D0 + + + rbb_bt_mode_ble + 0 + 0 + + + + + singen_ctrl0 + singen_ctrl0. + 0x20C + + + singen_en + 31 + 31 + + + singen_clkdiv_n + 29 + 30 + + + singen_unsign_en + 28 + 28 + + + singen_inc_step0 + 16 + 25 + + + singen_inc_step1 + 0 + 9 + + + + + singen_ctrl1 + singen_ctrl1. + 0x210 + + + singen_mode_i + 28 + 31 + + + singen_clkdiv_i + 16 + 25 + + + singen_mode_q + 12 + 15 + + + singen_clkdiv_q + 0 + 9 + + + + + singen_ctrl2 + singen_ctrl2. + 0x214 + + + singen_start_addr0_i + 22 + 31 + + + singen_start_addr1_i + 12 + 21 + + + singen_gain_i + 0 + 10 + + + + + singen_ctrl3 + singen_ctrl3. + 0x218 + + + singen_start_addr0_q + 22 + 31 + + + singen_start_addr1_q + 12 + 21 + + + singen_gain_q + 0 + 10 + + + + + singen_ctrl4 + singen_ctrl4. + 0x21C + + + singen_fix_en_i + 28 + 28 + + + singen_fix_i + 16 + 27 + + + singen_fix_en_q + 12 + 12 + + + singen_fix_q + 0 + 11 + + + + + rfif_dfe_ctrl0 + rfif_dfe_ctrl0. + 0x220 + + + test_sel + 28 + 31 + + + bbmode_4s_en + 27 + 27 + + + bbmode_4s + 26 + 26 + + + wifimode_4s_en + 25 + 25 + + + wifimode_4s + 23 + 24 + + + rf_ch_ind_ble_4s_en + 22 + 22 + + + rf_ch_ind_ble_4s + 15 + 21 + + + pad_dac_clkout_inv_en + 14 + 14 + + + pad_adc_clkout_inv_en + 13 + 13 + + + tx_test_sel + 11 + 12 + + + rx_test_sel + 9 + 10 + + + tx_dfe_en_4s_en + 8 + 8 + + + tx_dfe_en_4s + 7 + 7 + + + rx_dfe_en_4s_en + 6 + 6 + + + rx_dfe_en_4s + 5 + 5 + + + rfckg_dac_afifo_inv + 4 + 4 + + + rfckg_adc_clkout_sel + 3 + 3 + + + rfckg_adc_afifo_inv + 2 + 2 + + + rfckg_txclk_4s_on + 1 + 1 + + + rfckg_rxclk_4s_on + 0 + 0 + + + + + rfif_test_read + rfif_test_read. + 0x224 + + + test_read + 0 + 31 + + + + + rfif_dig_ctrl + rfif_dig_ctrl. + 0x228 + + + rfif_ppud_manaual_en + 30 + 30 + + + rfif_ppud_cnt1 + 25 + 29 + + + rfif_ppud_cnt2 + 16 + 24 + + + rfif_int_lo_unlocked_mask + 3 + 3 + + + rfckg_rxclk_div2_mode + 2 + 2 + + + test_gc_from_pad_en + 1 + 1 + + + test_from_pad_en + 0 + 0 + + + + + rf_data_temp_0 + rf_data_temp_0. + 0x22C + + + rf_data_temp_0 + 0 + 31 + + + + + rf_data_temp_1 + rf_data_temp_1. + 0x230 + + + rf_data_temp_1 + 0 + 31 + + + + + rf_data_temp_2 + rf_data_temp_2. + 0x234 + + + rf_data_temp_2 + 0 + 31 + + + + + rf_data_temp_3 + rf_data_temp_3. + 0x238 + + + rf_data_temp_3 + 0 + 31 + + + + + rf_sram_ctrl0 + rf_sram_ctrl0. + 0x23C + + + rf_sram_ext_clr + 19 + 19 + + + rf_sram_swap + 18 + 18 + + + rf_sram_link_mode + 16 + 17 + + + rf_sram_link_dly + 0 + 15 + + + + + rf_sram_ctrl1 + rf_sram_ctrl1. + 0x240 + + + rf_sram_adc_done_cnt + 16 + 31 + + + rf_sram_adc_sts_clr + 3 + 3 + + + rf_sram_adc_loop_en + 2 + 2 + + + rf_sram_adc_en + 1 + 1 + + + rf_sram_adc_done + 0 + 0 + + + + + rf_sram_ctrl2 + rf_sram_ctrl2. + 0x244 + + + rf_sram_adc_addr_start + 16 + 31 + + + rf_sram_adc_addr_end + 0 + 15 + + + + + rf_sram_ctrl3 + rf_sram_ctrl3. + 0x248 + + + rf_sram_adc_sts + 0 + 31 + + + + + rf_sram_ctrl4 + rf_sram_ctrl4. + 0x24C + + + rf_sram_dac_done_cnt + 16 + 31 + + + rf_sram_dac_sts_clr + 3 + 3 + + + rf_sram_dac_loop_en + 2 + 2 + + + rf_sram_dac_en + 1 + 1 + + + rf_sram_dac_done + 0 + 0 + + + + + rf_sram_ctrl5 + rf_sram_ctrl5. + 0x250 + + + rf_sram_dac_addr_start + 16 + 31 + + + rf_sram_dac_addr_end + 0 + 15 + + + + + rf_sram_ctrl6 + rf_sram_ctrl6. + 0x254 + + + rf_sram_dac_sts + 0 + 31 + + + + + rf_ical_ctrl0 + rf_ical_ctrl0. + 0x258 + + + rf_ical_f_ud_inv_en + 31 + 31 + + + rf_ical_a_ud_inv_en + 30 + 30 + + + rf_ical_f_cnt_n + 20 + 29 + + + rf_ical_a_cnt_n + 10 + 19 + + + rf_ical_r_cnt_n + 0 + 9 + + + + + rf_ical_ctrl1 + rf_ical_ctrl1. + 0x25C + + + rf_ical_r_os_i + 20 + 29 + + + rf_ical_r_os_q + 10 + 19 + + + rf_ical_r_avg_n + 0 + 4 + + + + + rf_ical_ctrl2 + rf_ical_ctrl2. + 0x260 + + + rf_ical_period_n + 0 + 15 + + + + + rf_fsm_ctrl0 + rf_fsm_ctrl0. + 0x264 + + + rf_ch_ind_wifi + 0 + 11 + + + + + rf_fsm_ctrl1 + rf_fsm_ctrl1. + 0x268 + + + rf_fsm_pu_pa_dly_n + 20 + 29 + + + rf_fsm_lo_rdy_sbclr + 19 + 19 + + + rf_fsm_lo_rdy_4s_1 + 18 + 18 + + + rf_fsm_lo_rdy_rst + 17 + 17 + + + rf_fsm_lo_rdy + 16 + 16 + + + rf_fsm_lo_time + 0 + 15 + + + + + rf_fsm_ctrl2 + rf_fsm_ctrl2. + 0x26C + + + rf_fsm_dfe_rx_dly_n + 20 + 29 + + + rf_fsm_dfe_tx_dly_n + 10 + 19 + + + rf_trx_ble_4s_en + 6 + 6 + + + rf_trx_sw_ble_4s + 5 + 5 + + + rf_trx_en_ble_4s + 4 + 4 + + + rf_fsm_st_dbg_en + 3 + 3 + + + rf_fsm_st_dbg + 0 + 2 + + + + + rf_pkdet_ctrl0 + rf_pkdet_ctrl0. + 0x270 + + + pkdet_out_mode + 5 + 5 + + + pkdet_out_cnt_en + 4 + 4 + + + pkdet_out_cnt_sts + 0 + 3 + + + + + dfe_ctrl_0 + dfe_ctrl_0. + 0x600 + + + tx_dvga_gain_ctrl_hw + 31 + 31 + + + tx_dvga_gain_qdb + 24 + 30 + + + tx_iqc_gain_en + 23 + 23 + + + tx_iqc_gain + 12 + 22 + + + tx_iqc_phase_en + 10 + 10 + + + tx_iqc_phase + 0 + 9 + + + + + dfe_ctrl_1 + dfe_ctrl_1. + 0x604 + + + tx_dac_iq_swap + 31 + 31 + + + tx_dac_dat_format + 30 + 30 + + + tx_dac_os_q + 16 + 27 + + + tx_dac_os_i + 0 + 11 + + + + + dfe_ctrl_2 + dfe_ctrl_2. + 0x608 + + + rx_adc_iq_swap + 31 + 31 + + + rx_adc_dat_format + 30 + 30 + + + rx_adc_low_pow_en + 29 + 29 + + + rx_adc_dce_flt_en + 28 + 28 + + + rx_adc_os_q + 16 + 25 + + + rx_adc_os_i + 0 + 9 + + + + + dfe_ctrl_3 + dfe_ctrl_3. + 0x60C + + + rx_adc_4s_q_en + 26 + 26 + + + rx_adc_4s_q_val + 16 + 25 + + + rx_adc_4s_i_en + 10 + 10 + + + rx_adc_4s_i_val + 0 + 9 + + + + + dfe_ctrl_4 + dfe_ctrl_4. + 0x610 + + + rx_pf_i_en + 31 + 31 + + + rx_pf_q_en + 30 + 30 + + + rx_pf_th1 + 16 + 25 + + + rx_pf_th2 + 0 + 9 + + + + + dfe_ctrl_5 + dfe_ctrl_5. + 0x614 + + + rx_iqc_gain_en + 23 + 23 + + + rx_iqc_gain + 12 + 22 + + + rx_iqc_phase_en + 10 + 10 + + + rx_iqc_phase + 0 + 9 + + + + + dfe_ctrl_6 + dfe_ctrl_6. + 0x618 + + + rx_pm_in_sel + 30 + 31 + + + rx_pm_en + 29 + 29 + + + rx_pm_done + 28 + 28 + + + rx_pm_freqshift_en + 20 + 20 + + + rx_pm_freqshift_cw + 0 + 19 + + + + + dfe_ctrl_7 + dfe_ctrl_7. + 0x61C + + + rx_pm_acc_len + 16 + 31 + + + rx_pm_start_ofs + 0 + 15 + + + + + dfe_ctrl_8 + dfe_ctrl_8. + 0x620 + + + rx_pm_iqacc_i + 0 + 24 + + + + + dfe_ctrl_9 + dfe_ctrl_9. + 0x624 + + + rx_pm_iqacc_q + 0 + 24 + + + + + dfe_ctrl_10 + dfe_ctrl_10. + 0x628 + + + dfe_dac_raw_q + 16 + 26 + + + dfe_dac_raw_i + 0 + 10 + + + + + dfe_ctrl_11 + dfe_ctrl_11. + 0x62C + + + dfe_adc_raw_q + 16 + 25 + + + dfe_adc_raw_i + 0 + 9 + + + + + dfe_ctrl_12 + dfe_ctrl_12. + 0x630 + + + tx_dvga_gain_qdb_gc3 + 24 + 30 + + + tx_dvga_gain_qdb_gc2 + 16 + 22 + + + tx_dvga_gain_qdb_gc1 + 8 + 14 + + + tx_dvga_gain_qdb_gc0 + 0 + 6 + + + + + dfe_ctrl_13 + dfe_ctrl_13. + 0x634 + + + tx_dvga_gain_qdb_gc7 + 24 + 30 + + + tx_dvga_gain_qdb_gc6 + 16 + 22 + + + tx_dvga_gain_qdb_gc5 + 8 + 14 + + + tx_dvga_gain_qdb_gc4 + 0 + 6 + + + + + dfe_ctrl_14 + dfe_ctrl_14. + 0x638 + + + tx_dvga_gain_qdb_gc11 + 24 + 30 + + + tx_dvga_gain_qdb_gc10 + 16 + 22 + + + tx_dvga_gain_qdb_gc9 + 8 + 14 + + + tx_dvga_gain_qdb_gc8 + 0 + 6 + + + + + dfe_ctrl_15 + dfe_ctrl_15. + 0x63C + + + tx_dvga_gain_qdb_gc15 + 24 + 30 + + + tx_dvga_gain_qdb_gc14 + 16 + 22 + + + tx_dvga_gain_qdb_gc13 + 8 + 14 + + + tx_dvga_gain_qdb_gc12 + 0 + 6 + + + + + dfe_ctrl_16 + dfe_ctrl_16. + 0x640 + + + rf_tbb_ind_gc7 + 28 + 30 + + + rf_tbb_ind_gc6 + 24 + 26 + + + rf_tbb_ind_gc5 + 20 + 22 + + + rf_tbb_ind_gc4 + 16 + 18 + + + rf_tbb_ind_gc3 + 12 + 14 + + + rf_tbb_ind_gc2 + 8 + 10 + + + rf_tbb_ind_gc1 + 4 + 6 + + + rf_tbb_ind_gc0 + 0 + 2 + + + + + dfe_ctrl_17 + dfe_ctrl_17. + 0x644 + + + rf_tbb_ind_gc15 + 28 + 30 + + + rf_tbb_ind_gc14 + 24 + 26 + + + rf_tbb_ind_gc13 + 20 + 22 + + + rf_tbb_ind_gc12 + 16 + 18 + + + rf_tbb_ind_gc11 + 12 + 14 + + + rf_tbb_ind_gc10 + 8 + 10 + + + rf_tbb_ind_gc9 + 4 + 6 + + + rf_tbb_ind_gc8 + 0 + 2 + + + + + dfe_ctrl_18 + dfe_ctrl_18. + 0x648 + + + tx_dvga_gain_qdb_ble_gc2 + 16 + 22 + + + tx_dvga_gain_qdb_ble_gc1 + 8 + 14 + + + tx_dvga_gain_qdb_ble_gc0 + 0 + 6 + + + + + + + gpip + gpip. + 0x40002000 + gpip + 32 + read-write + + 0 + 0x1000 + registers + + + + gpadc_config + gpadc_config. + 0x0 + + + rsvd_31_24 + 24 + 31 + + + gpadc_fifo_thl + 22 + 23 + + + gpadc_fifo_data_count + 16 + 21 + + + gpadc_fifo_underrun_mask + 14 + 14 + + + gpadc_fifo_overrun_mask + 13 + 13 + + + gpadc_rdy_mask + 12 + 12 + + + gpadc_fifo_underrun_clr + 10 + 10 + + + gpadc_fifo_overrun_clr + 9 + 9 + + + gpadc_rdy_clr + 8 + 8 + + + gpadc_fifo_underrun + 6 + 6 + + + gpadc_fifo_overrun + 5 + 5 + + + gpadc_rdy + 4 + 4 + + + gpadc_fifo_full + 3 + 3 + + + gpadc_fifo_ne + 2 + 2 + + + gpadc_fifo_clr + 1 + 1 + + + gpadc_dma_en + 0 + 0 + + + + + gpadc_dma_rdata + gpadc_dma_rdata. + 0x4 + + + rsvd_31_26 + 26 + 31 + + + gpadc_dma_rdata + 0 + 25 + + + + + gpdac_config + gpdac_config. + 0x40 + + + rsvd_31_24 + 24 + 31 + + + gpdac_ch_b_sel + 20 + 23 + + + gpdac_ch_a_sel + 16 + 19 + + + gpdac_mode + 8 + 10 + + + dsm_mode + 4 + 5 + + + gpdac_en2 + 1 + 1 + + + gpdac_en + 0 + 0 + + + + + gpdac_dma_config + gpdac_dma_config. + 0x44 + + + gpdac_dma_format + 4 + 5 + + + gpdac_dma_tx_en + 0 + 0 + + + + + gpdac_dma_wdata + gpdac_dma_wdata. + 0x48 + + + gpdac_dma_wdata + 0 + 31 + + + + + gpdac_tx_fifo_status + gpdac_tx_fifo_status. + 0x4C + + + TxFifoWrPtr + 8 + 9 + + + TxFifoRdPtr + 4 + 6 + + + tx_cs + 2 + 3 + + + tx_fifo_full + 1 + 1 + + + tx_fifo_empty + 0 + 0 + + + + + + + sec_dbg + sec_dbg. + 0x40003000 + sec_dbg + 32 + read-write + + 0 + 0x1000 + registers + + + + sd_chip_id_low + sd_chip_id_low. + 0x0 + + + sd_chip_id_low + 0 + 31 + + + + + sd_chip_id_high + sd_chip_id_high. + 0x4 + + + sd_chip_id_high + 0 + 31 + + + + + sd_wifi_mac_low + sd_wifi_mac_low. + 0x8 + + + sd_wifi_mac_low + 0 + 31 + + + + + sd_wifi_mac_high + sd_wifi_mac_high. + 0xC + + + sd_wifi_mac_high + 0 + 31 + + + + + sd_dbg_pwd_low + sd_dbg_pwd_low. + 0x10 + + + sd_dbg_pwd_low + 0 + 31 + + + + + sd_dbg_pwd_high + sd_dbg_pwd_high. + 0x14 + + + sd_dbg_pwd_high + 0 + 31 + + + + + sd_status + sd_status. + 0x18 + + + sd_dbg_ena + 28 + 31 + + + sd_dbg_mode + 24 + 27 + + + sd_dbg_pwd_cnt + 4 + 23 + + + sd_dbg_cci_clk_sel + 3 + 3 + + + sd_dbg_cci_read_en + 2 + 2 + + + sd_dbg_pwd_trig + 1 + 1 + + + sd_dbg_pwd_busy + 0 + 0 + + + + + sd_dbg_reserved + sd_dbg_reserved. + 0x1C + + + sd_dbg_reserved + 0 + 31 + + + + + + + sec_eng + sec_eng. + 0x40004000 + sec_eng + 32 + read-write + + 0 + 0x1000 + registers + + + + se_sha_0_ctrl + se_sha_0_ctrl. + 0x0 + + + se_sha_0_msg_len + 16 + 31 + + + se_sha_0_link_mode + 15 + 15 + + + se_sha_0_int_mask + 11 + 11 + + + se_sha_0_int_set_1t + 10 + 10 + + + se_sha_0_int_clr_1t + 9 + 9 + + + se_sha_0_int + 8 + 8 + + + se_sha_0_hash_sel + 6 + 6 + + + se_sha_0_en + 5 + 5 + + + se_sha_0_mode + 2 + 4 + + + se_sha_0_trig_1t + 1 + 1 + + + se_sha_0_busy + 0 + 0 + + + + + se_sha_0_msa + se_sha_0_msa. + 0x4 + + + se_sha_0_msa + 0 + 31 + + + + + se_sha_0_status + se_sha_0_status. + 0x8 + + + se_sha_0_status + 0 + 31 + + + + + se_sha_0_endian + se_sha_0_endian. + 0xC + + + se_sha_0_dout_endian + 0 + 0 + + + + + se_sha_0_hash_l_0 + se_sha_0_hash_l_0. + 0x10 + + + se_sha_0_hash_l_0 + 0 + 31 + + + + + se_sha_0_hash_l_1 + se_sha_0_hash_l_1. + 0x14 + + + se_sha_0_hash_l_1 + 0 + 31 + + + + + se_sha_0_hash_l_2 + se_sha_0_hash_l_2. + 0x18 + + + se_sha_0_hash_l_2 + 0 + 31 + + + + + se_sha_0_hash_l_3 + se_sha_0_hash_l_3. + 0x1C + + + se_sha_0_hash_l_3 + 0 + 31 + + + + + se_sha_0_hash_l_4 + se_sha_0_hash_l_4. + 0x20 + + + se_sha_0_hash_l_4 + 0 + 31 + + + + + se_sha_0_hash_l_5 + se_sha_0_hash_l_5. + 0x24 + + + se_sha_0_hash_l_5 + 0 + 31 + + + + + se_sha_0_hash_l_6 + se_sha_0_hash_l_6. + 0x28 + + + se_sha_0_hash_l_6 + 0 + 31 + + + + + se_sha_0_hash_l_7 + se_sha_0_hash_l_7. + 0x2C + + + se_sha_0_hash_l_7 + 0 + 31 + + + + + se_sha_0_hash_h_0 + se_sha_0_hash_h_0. + 0x30 + + + se_sha_0_hash_h_0 + 0 + 31 + + + + + se_sha_0_hash_h_1 + se_sha_0_hash_h_1. + 0x34 + + + se_sha_0_hash_h_1 + 0 + 31 + + + + + se_sha_0_hash_h_2 + se_sha_0_hash_h_2. + 0x38 + + + se_sha_0_hash_h_2 + 0 + 31 + + + + + se_sha_0_hash_h_3 + se_sha_0_hash_h_3. + 0x3C + + + se_sha_0_hash_h_3 + 0 + 31 + + + + + se_sha_0_hash_h_4 + se_sha_0_hash_h_4. + 0x40 + + + se_sha_0_hash_h_4 + 0 + 31 + + + + + se_sha_0_hash_h_5 + se_sha_0_hash_h_5. + 0x44 + + + se_sha_0_hash_h_5 + 0 + 31 + + + + + se_sha_0_hash_h_6 + se_sha_0_hash_h_6. + 0x48 + + + se_sha_0_hash_h_6 + 0 + 31 + + + + + se_sha_0_hash_h_7 + se_sha_0_hash_h_7. + 0x4C + + + se_sha_0_hash_h_7 + 0 + 31 + + + + + se_sha_0_link + se_sha_0_link. + 0x50 + + + se_sha_0_lca + 0 + 31 + + + + + se_sha_0_ctrl_prot + se_sha_0_ctrl_prot. + 0xFC + + + se_sha_id1_en + 2 + 2 + + + se_sha_id0_en + 1 + 1 + + + se_sha_prot_en + 0 + 0 + + + + + se_aes_0_ctrl + se_aes_0_ctrl. + 0x100 + + + se_aes_0_msg_len + 16 + 31 + + + se_aes_0_link_mode + 15 + 15 + + + se_aes_0_iv_sel + 14 + 14 + + + se_aes_0_block_mode + 12 + 13 + + + se_aes_0_int_mask + 11 + 11 + + + se_aes_0_int_set_1t + 10 + 10 + + + se_aes_0_int_clr_1t + 9 + 9 + + + se_aes_0_int + 8 + 8 + + + se_aes_0_hw_key_en + 7 + 7 + + + se_aes_0_dec_key_sel + 6 + 6 + + + se_aes_0_dec_en + 5 + 5 + + + se_aes_0_mode + 3 + 4 + + + se_aes_0_en + 2 + 2 + + + se_aes_0_trig_1t + 1 + 1 + + + se_aes_0_busy + 0 + 0 + + + + + se_aes_0_msa + se_aes_0_msa. + 0x104 + + + se_aes_0_msa + 0 + 31 + + + + + se_aes_0_mda + se_aes_0_mda. + 0x108 + + + se_aes_0_mda + 0 + 31 + + + + + se_aes_0_status + se_aes_0_status. + 0x10C + + + se_aes_0_status + 0 + 31 + + + + + se_aes_0_iv_0 + se_aes_0_iv_0. + 0x110 + + + se_aes_0_iv_0 + 0 + 31 + + + + + se_aes_0_iv_1 + se_aes_0_iv_1. + 0x114 + + + se_aes_0_iv_1 + 0 + 31 + + + + + se_aes_0_iv_2 + se_aes_0_iv_2. + 0x118 + + + se_aes_0_iv_2 + 0 + 31 + + + + + se_aes_0_iv_3 + se_aes_0_iv_3. + 0x11C + + + se_aes_0_iv_3 + 0 + 31 + + + + + se_aes_0_key_0 + se_aes_0_key_0. + 0x120 + + + se_aes_0_key_0 + 0 + 31 + + + + + se_aes_0_key_1 + se_aes_0_key_1. + 0x124 + + + se_aes_0_key_1 + 0 + 31 + + + + + se_aes_0_key_2 + se_aes_0_key_2. + 0x128 + + + se_aes_0_key_2 + 0 + 31 + + + + + se_aes_0_key_3 + se_aes_0_key_3. + 0x12C + + + se_aes_0_key_3 + 0 + 31 + + + + + se_aes_0_key_4 + se_aes_0_key_4. + 0x130 + + + se_aes_0_key_4 + 0 + 31 + + + + + se_aes_0_key_5 + se_aes_0_key_5. + 0x134 + + + se_aes_0_key_5 + 0 + 31 + + + + + se_aes_0_key_6 + se_aes_0_key_6. + 0x138 + + + se_aes_0_key_6 + 0 + 31 + + + + + se_aes_0_key_7 + se_aes_0_key_7. + 0x13C + + + se_aes_0_key_7 + 0 + 31 + + + + + se_aes_0_key_sel_0 + se_aes_0_key_sel_0. + 0x140 + + + se_aes_0_key_sel_0 + 0 + 1 + + + + + se_aes_0_key_sel_1 + se_aes_0_key_sel_1. + 0x144 + + + se_aes_0_key_sel_1 + 0 + 1 + + + + + se_aes_0_endian + se_aes_0_endian. + 0x148 + + + se_aes_0_ctr_len + 30 + 31 + + + se_aes_0_iv_endian + 3 + 3 + + + se_aes_0_key_endian + 2 + 2 + + + se_aes_0_din_endian + 1 + 1 + + + se_aes_0_dout_endian + 0 + 0 + + + + + se_aes_0_sboot + se_aes_0_sboot. + 0x14C + + + se_aes_0_sboot_key_sel + 0 + 0 + + + + + se_aes_0_link + se_aes_0_link. + 0x150 + + + se_aes_0_lca + 0 + 31 + + + + + se_aes_0_ctrl_prot + se_aes_0_ctrl_prot. + 0x1FC + + + se_aes_id1_en + 2 + 2 + + + se_aes_id0_en + 1 + 1 + + + se_aes_prot_en + 0 + 0 + + + + + se_trng_0_ctrl_0 + se_trng_0_ctrl_0. + 0x200 + + + se_trng_0_manual_en + 15 + 15 + + + se_trng_0_manual_reseed + 14 + 14 + + + se_trng_0_manual_fun_sel + 13 + 13 + + + se_trng_0_int_mask + 11 + 11 + + + se_trng_0_int_set_1t + 10 + 10 + + + se_trng_0_int_clr_1t + 9 + 9 + + + se_trng_0_int + 8 + 8 + + + se_trng_0_ht_error + 4 + 4 + + + se_trng_0_dout_clr_1t + 3 + 3 + + + se_trng_0_en + 2 + 2 + + + se_trng_0_trig_1t + 1 + 1 + + + se_trng_0_busy + 0 + 0 + + + + + se_trng_0_status + se_trng_0_status. + 0x204 + + + se_trng_0_status + 0 + 31 + + + + + se_trng_0_dout_0 + se_trng_0_dout_0. + 0x208 + + + se_trng_0_dout_0 + 0 + 31 + + + + + se_trng_0_dout_1 + se_trng_0_dout_1. + 0x20C + + + se_trng_0_dout_1 + 0 + 31 + + + + + se_trng_0_dout_2 + se_trng_0_dout_2. + 0x210 + + + se_trng_0_dout_2 + 0 + 31 + + + + + se_trng_0_dout_3 + se_trng_0_dout_3. + 0x214 + + + se_trng_0_dout_3 + 0 + 31 + + + + + se_trng_0_dout_4 + se_trng_0_dout_4. + 0x218 + + + se_trng_0_dout_4 + 0 + 31 + + + + + se_trng_0_dout_5 + se_trng_0_dout_5. + 0x21C + + + se_trng_0_dout_5 + 0 + 31 + + + + + se_trng_0_dout_6 + se_trng_0_dout_6. + 0x220 + + + se_trng_0_dout_6 + 0 + 31 + + + + + se_trng_0_dout_7 + se_trng_0_dout_7. + 0x224 + + + se_trng_0_dout_7 + 0 + 31 + + + + + se_trng_0_test + se_trng_0_test. + 0x228 + + + se_trng_0_ht_alarm_n + 4 + 11 + + + se_trng_0_ht_dis + 3 + 3 + + + se_trng_0_cp_bypass + 2 + 2 + + + se_trng_0_cp_test_en + 1 + 1 + + + se_trng_0_test_en + 0 + 0 + + + + + se_trng_0_ctrl_1 + se_trng_0_ctrl_1. + 0x22C + + + se_trng_0_reseed_n_lsb + 0 + 31 + + + + + se_trng_0_ctrl_2 + se_trng_0_ctrl_2. + 0x230 + + + se_trng_0_reseed_n_msb + 0 + 15 + + + + + se_trng_0_ctrl_3 + se_trng_0_ctrl_3. + 0x234 + + + se_trng_0_rosc_en + 31 + 31 + + + se_trng_0_ht_od_en + 26 + 26 + + + se_trng_0_ht_apt_c + 16 + 25 + + + se_trng_0_ht_rct_c + 8 + 15 + + + se_trng_0_cp_ratio + 0 + 7 + + + + + se_trng_0_test_out_0 + se_trng_0_test_out_0. + 0x240 + + + se_trng_0_test_out_0 + 0 + 31 + + + + + se_trng_0_test_out_1 + se_trng_0_test_out_1. + 0x244 + + + se_trng_0_test_out_1 + 0 + 31 + + + + + se_trng_0_test_out_2 + se_trng_0_test_out_2. + 0x248 + + + se_trng_0_test_out_2 + 0 + 31 + + + + + se_trng_0_test_out_3 + se_trng_0_test_out_3. + 0x24C + + + se_trng_0_test_out_3 + 0 + 31 + + + + + se_trng_0_ctrl_prot + se_trng_0_ctrl_prot. + 0x2FC + + + se_trng_id1_en + 2 + 2 + + + se_trng_id0_en + 1 + 1 + + + se_trng_prot_en + 0 + 0 + + + + + se_pka_0_ctrl_0 + se_pka_0_ctrl_0. + 0x300 + + + se_pka_0_status + 17 + 31 + + + se_pka_0_status_clr_1t + 16 + 16 + + + se_pka_0_ram_clr_md + 13 + 13 + + + se_pka_0_endian + 12 + 12 + + + se_pka_0_int_mask + 11 + 11 + + + se_pka_0_int_set + 10 + 10 + + + se_pka_0_int_clr_1t + 9 + 9 + + + se_pka_0_int + 8 + 8 + + + se_pka_0_prot_md + 4 + 7 + + + se_pka_0_en + 3 + 3 + + + se_pka_0_busy + 2 + 2 + + + se_pka_0_done_clr_1t + 1 + 1 + + + se_pka_0_done + 0 + 0 + + + + + se_pka_0_seed + se_pka_0_seed. + 0x30C + + + se_pka_0_seed + 0 + 31 + + + + + se_pka_0_ctrl_1 + se_pka_0_ctrl_1. + 0x310 + + + se_pka_0_hbypass + 3 + 3 + + + se_pka_0_hburst + 0 + 2 + + + + + se_pka_0_rw + se_pka_0_rw. + 0x340 + + + + se_pka_0_rw_burst + se_pka_0_rw_burst. + 0x360 + + + + se_pka_0_ctrl_prot + se_pka_0_ctrl_prot. + 0x3FC + + + se_pka_id1_en + 2 + 2 + + + se_pka_id0_en + 1 + 1 + + + se_pka_prot_en + 0 + 0 + + + + + se_cdet_0_ctrl_0 + se_cdet_0_ctrl_0. + 0x400 + + + se_cdet_0_g_loop_min + 24 + 31 + + + se_cdet_0_g_loop_max + 16 + 23 + + + se_cdet_0_status + 2 + 15 + + + se_cdet_0_error + 1 + 1 + + + se_cdet_0_en + 0 + 0 + + + + + se_cdet_0_ctrl_1 + se_cdet_0_ctrl_1. + 0x404 + + + se_cdet_0_g_slp_n + 16 + 23 + + + se_cdet_0_t_dly_n + 8 + 15 + + + se_cdet_0_t_loop_n + 0 + 7 + + + + + se_cdet_0_ctrl_prot + se_cdet_0_ctrl_prot. + 0x4FC + + + se_cdet_id1_en + 2 + 2 + + + se_cdet_id0_en + 1 + 1 + + + se_cdet_prot_en + 0 + 0 + + + + + se_gmac_0_ctrl_0 + se_gmac_0_ctrl_0. + 0x500 + + + se_gmac_0_x_endian + 14 + 14 + + + se_gmac_0_h_endian + 13 + 13 + + + se_gmac_0_t_endian + 12 + 12 + + + se_gmac_0_int_mask + 11 + 11 + + + se_gmac_0_int_set_1t + 10 + 10 + + + se_gmac_0_int_clr_1t + 9 + 9 + + + se_gmac_0_int + 8 + 8 + + + se_gmac_0_en + 2 + 2 + + + se_gmac_0_trig_1t + 1 + 1 + + + se_gmac_0_busy + 0 + 0 + + + + + se_gmac_0_lca + se_gmac_0_lca. + 0x504 + + + se_gmac_0_lca + 0 + 31 + + + + + se_gmac_0_status + se_gmac_0_status. + 0x508 + + + se_gmac_0_status + 0 + 31 + + + + + se_gmac_0_ctrl_prot + se_gmac_0_ctrl_prot. + 0x5FC + + + se_gmac_id1_en + 2 + 2 + + + se_gmac_id0_en + 1 + 1 + + + se_gmac_prot_en + 0 + 0 + + + + + se_ctrl_prot_rd + se_ctrl_prot_rd. + 0xF00 + + + se_dbg_dis + 31 + 31 + + + se_gmac_id1_en_rd + 22 + 22 + + + se_gmac_id0_en_rd + 21 + 21 + + + se_gmac_prot_en_rd + 20 + 20 + + + se_cdet_id1_en_rd + 18 + 18 + + + se_cdet_id0_en_rd + 17 + 17 + + + se_cdet_prot_en_rd + 16 + 16 + + + se_pka_id1_en_rd + 14 + 14 + + + se_pka_id0_en_rd + 13 + 13 + + + se_pka_prot_en_rd + 12 + 12 + + + se_trng_id1_en_rd + 10 + 10 + + + se_trng_id0_en_rd + 9 + 9 + + + se_trng_prot_en_rd + 8 + 8 + + + se_aes_id1_en_rd + 6 + 6 + + + se_aes_id0_en_rd + 5 + 5 + + + se_aes_prot_en_rd + 4 + 4 + + + se_sha_id1_en_rd + 2 + 2 + + + se_sha_id0_en_rd + 1 + 1 + + + se_sha_prot_en_rd + 0 + 0 + + + + + se_ctrl_reserved_0 + se_ctrl_reserved_0. + 0xF04 + + + se_ctrl_reserved_0 + 0 + 31 + + + + + se_ctrl_reserved_1 + se_ctrl_reserved_1. + 0xF08 + + + se_ctrl_reserved_1 + 0 + 31 + + + + + se_ctrl_reserved_2 + se_ctrl_reserved_2. + 0xF0C + + + se_ctrl_reserved_2 + 0 + 31 + + + + + + + tzc_sec + tzc_sec. + 0x40005000 + tzc_sec + 32 + read-write + + 0 + 0x1000 + registers + + + + tzc_rom_ctrl + tzc_rom_ctrl. + 0x40 + + + tzc_sboot_done + 28 + 31 + + + tzc_rom1_r1_lock + 27 + 27 + + + tzc_rom1_r0_lock + 26 + 26 + + + tzc_rom0_r1_lock + 25 + 25 + + + tzc_rom0_r0_lock + 24 + 24 + + + tzc_rom1_r1_en + 19 + 19 + + + tzc_rom1_r0_en + 18 + 18 + + + tzc_rom0_r1_en + 17 + 17 + + + tzc_rom0_r0_en + 16 + 16 + + + tzc_rom1_r1_id1_en + 11 + 11 + + + tzc_rom1_r0_id1_en + 10 + 10 + + + tzc_rom0_r1_id1_en + 9 + 9 + + + tzc_rom0_r0_id1_en + 8 + 8 + + + tzc_rom1_r1_id0_en + 3 + 3 + + + tzc_rom1_r0_id0_en + 2 + 2 + + + tzc_rom0_r1_id0_en + 1 + 1 + + + tzc_rom0_r0_id0_en + 0 + 0 + + + + + tzc_rom0_r0 + tzc_rom0_r0. + 0x44 + + + tzc_rom0_r0_start + 16 + 31 + + + tzc_rom0_r0_end + 0 + 15 + + + + + tzc_rom0_r1 + tzc_rom0_r1. + 0x48 + + + tzc_rom0_r1_start + 16 + 31 + + + tzc_rom0_r1_end + 0 + 15 + + + + + tzc_rom1_r0 + tzc_rom1_r0. + 0x4C + + + tzc_rom1_r0_start + 16 + 31 + + + tzc_rom1_r0_end + 0 + 15 + + + + + tzc_rom1_r1 + tzc_rom1_r1. + 0x50 + + + tzc_rom1_r1_start + 16 + 31 + + + tzc_rom1_r1_end + 0 + 15 + + + + + + + tzc_nsec + tzc_nsec. + 0x40006000 + tzc_nsec + 32 + read-write + + 0 + 0x1000 + registers + + + + tzc_rom_ctrl + tzc_rom_ctrl. + 0x40 + + + tzc_sboot_done + 28 + 31 + + + tzc_rom1_r1_lock + 27 + 27 + + + tzc_rom1_r0_lock + 26 + 26 + + + tzc_rom0_r1_lock + 25 + 25 + + + tzc_rom0_r0_lock + 24 + 24 + + + tzc_rom1_r1_en + 19 + 19 + + + tzc_rom1_r0_en + 18 + 18 + + + tzc_rom0_r1_en + 17 + 17 + + + tzc_rom0_r0_en + 16 + 16 + + + tzc_rom1_r1_id1_en + 11 + 11 + + + tzc_rom1_r0_id1_en + 10 + 10 + + + tzc_rom0_r1_id1_en + 9 + 9 + + + tzc_rom0_r0_id1_en + 8 + 8 + + + tzc_rom1_r1_id0_en + 3 + 3 + + + tzc_rom1_r0_id0_en + 2 + 2 + + + tzc_rom0_r1_id0_en + 1 + 1 + + + tzc_rom0_r0_id0_en + 0 + 0 + + + + + tzc_rom0_r0 + tzc_rom0_r0. + 0x44 + + + tzc_rom0_r0_start + 16 + 31 + + + tzc_rom0_r0_end + 0 + 15 + + + + + tzc_rom0_r1 + tzc_rom0_r1. + 0x48 + + + tzc_rom0_r1_start + 16 + 31 + + + tzc_rom0_r1_end + 0 + 15 + + + + + tzc_rom1_r0 + tzc_rom1_r0. + 0x4C + + + tzc_rom1_r0_start + 16 + 31 + + + tzc_rom1_r0_end + 0 + 15 + + + + + tzc_rom1_r1 + tzc_rom1_r1. + 0x50 + + + tzc_rom1_r1_start + 16 + 31 + + + tzc_rom1_r1_end + 0 + 15 + + + + + + + ef_data_0 + ef_data_0. + 0x40007000 + ef_data_0 + 32 + read-write + + 0 + 0x1000 + registers + + + + ef_cfg_0 + ef_cfg_0. + 0x0 + + + ef_dbg_mode + 28 + 31 + + + ef_dbg_jtag_0_dis + 26 + 27 + + + ef_dbg_jtag_1_dis + 24 + 25 + + + ef_efuse_dbg_dis + 23 + 23 + + + ef_se_dbg_dis + 22 + 22 + + + ef_cpu_rst_dbg_dis + 21 + 21 + + + ef_cpu1_dis + 20 + 20 + + + ef_sf_dis + 19 + 19 + + + ef_cam_dis + 18 + 18 + + + ef_0_key_enc_en + 17 + 17 + + + ef_wifi_dis + 16 + 16 + + + ef_ble_dis + 15 + 15 + + + ef_sdu_dis + 14 + 14 + + + ef_sw_usage_1 + 12 + 13 + + + ef_boot_sel + 8 + 11 + + + ef_cpu0_enc_en + 7 + 7 + + + ef_cpu1_enc_en + 6 + 6 + + + ef_sboot_en + 4 + 5 + + + ef_sboot_sign_mode + 2 + 3 + + + ef_sf_aes_mode + 0 + 1 + + + + + ef_dbg_pwd_low + ef_dbg_pwd_low. + 0x4 + + + ef_dbg_pwd_low + 0 + 31 + + + + + ef_dbg_pwd_high + ef_dbg_pwd_high. + 0x8 + + + ef_dbg_pwd_high + 0 + 31 + + + + + ef_ana_trim_0 + ef_ana_trim_0. + 0xC + + + ef_ana_trim_0 + 0 + 31 + + + + + ef_sw_usage_0 + ef_sw_usage_0. + 0x10 + + + ef_sw_usage_0 + 0 + 31 + + + + + ef_wifi_mac_low + ef_wifi_mac_low. + 0x14 + + + ef_wifi_mac_low + 0 + 31 + + + + + ef_wifi_mac_high + ef_wifi_mac_high. + 0x18 + + + ef_wifi_mac_high + 0 + 31 + + + + + ef_key_slot_0_w0 + ef_key_slot_0_w0. + 0x1C + + + ef_key_slot_0_w0 + 0 + 31 + + + + + ef_key_slot_0_w1 + ef_key_slot_0_w1. + 0x20 + + + ef_key_slot_0_w1 + 0 + 31 + + + + + ef_key_slot_0_w2 + ef_key_slot_0_w2. + 0x24 + + + ef_key_slot_0_w2 + 0 + 31 + + + + + ef_key_slot_0_w3 + ef_key_slot_0_w3. + 0x28 + + + ef_key_slot_0_w3 + 0 + 31 + + + + + ef_key_slot_1_w0 + ef_key_slot_1_w0. + 0x2C + + + ef_key_slot_1_w0 + 0 + 31 + + + + + ef_key_slot_1_w1 + ef_key_slot_1_w1. + 0x30 + + + ef_key_slot_1_w1 + 0 + 31 + + + + + ef_key_slot_1_w2 + ef_key_slot_1_w2. + 0x34 + + + ef_key_slot_1_w2 + 0 + 31 + + + + + ef_key_slot_1_w3 + ef_key_slot_1_w3. + 0x38 + + + ef_key_slot_1_w3 + 0 + 31 + + + + + ef_key_slot_2_w0 + ef_key_slot_2_w0. + 0x3C + + + ef_key_slot_2_w0 + 0 + 31 + + + + + ef_key_slot_2_w1 + ef_key_slot_2_w1. + 0x40 + + + ef_key_slot_2_w1 + 0 + 31 + + + + + ef_key_slot_2_w2 + ef_key_slot_2_w2. + 0x44 + + + ef_key_slot_2_w2 + 0 + 31 + + + + + ef_key_slot_2_w3 + ef_key_slot_2_w3. + 0x48 + + + ef_key_slot_2_w3 + 0 + 31 + + + + + ef_key_slot_3_w0 + ef_key_slot_3_w0. + 0x4C + + + ef_key_slot_3_w0 + 0 + 31 + + + + + ef_key_slot_3_w1 + ef_key_slot_3_w1. + 0x50 + + + ef_key_slot_3_w1 + 0 + 31 + + + + + ef_key_slot_3_w2 + ef_key_slot_3_w2. + 0x54 + + + ef_key_slot_3_w2 + 0 + 31 + + + + + ef_key_slot_3_w3 + ef_key_slot_3_w3. + 0x58 + + + ef_key_slot_3_w3 + 0 + 31 + + + + + ef_key_slot_4_w0 + ef_key_slot_4_w0. + 0x5C + + + ef_key_slot_4_w0 + 0 + 31 + + + + + ef_key_slot_4_w1 + ef_key_slot_4_w1. + 0x60 + + + ef_key_slot_4_w1 + 0 + 31 + + + + + ef_key_slot_4_w2 + ef_key_slot_4_w2. + 0x64 + + + ef_key_slot_4_w2 + 0 + 31 + + + + + ef_key_slot_4_w3 + ef_key_slot_4_w3. + 0x68 + + + ef_key_slot_4_w3 + 0 + 31 + + + + + ef_key_slot_5_w0 + ef_key_slot_5_w0. + 0x6C + + + ef_key_slot_5_w0 + 0 + 31 + + + + + ef_key_slot_5_w1 + ef_key_slot_5_w1. + 0x70 + + + ef_key_slot_5_w1 + 0 + 31 + + + + + ef_key_slot_5_w2 + ef_key_slot_5_w2. + 0x74 + + + ef_key_slot_5_w2 + 0 + 31 + + + + + ef_key_slot_5_w3 + ef_key_slot_5_w3. + 0x78 + + + ef_key_slot_5_w3 + 0 + 31 + + + + + ef_data_0_lock + ef_data_0_lock. + 0x7C + + + rd_lock_key_slot_5 + 31 + 31 + + + rd_lock_key_slot_4 + 30 + 30 + + + rd_lock_key_slot_3 + 29 + 29 + + + rd_lock_key_slot_2 + 28 + 28 + + + rd_lock_key_slot_1 + 27 + 27 + + + rd_lock_key_slot_0 + 26 + 26 + + + rd_lock_dbg_pwd + 25 + 25 + + + wr_lock_key_slot_5_h + 24 + 24 + + + wr_lock_key_slot_4_h + 23 + 23 + + + wr_lock_key_slot_3 + 22 + 22 + + + wr_lock_key_slot_2 + 21 + 21 + + + wr_lock_key_slot_1 + 20 + 20 + + + wr_lock_key_slot_0 + 19 + 19 + + + wr_lock_wifi_mac + 18 + 18 + + + wr_lock_sw_usage_0 + 17 + 17 + + + wr_lock_dbg_pwd + 16 + 16 + + + wr_lock_boot_mode + 15 + 15 + + + wr_lock_key_slot_5_l + 14 + 14 + + + wr_lock_key_slot_4_l + 13 + 13 + + + ef_ana_trim_1 + 0 + 12 + + + + + + + ef_data_1 + ef_data_1. + 0x40007000 + ef_data_1 + 32 + read-write + + 0 + 0x1000 + registers + + + + reg_key_slot_6_w0 + reg_key_slot_6_w0. + 0x80 + + + reg_key_slot_6_w0 + 0 + 31 + + + + + reg_key_slot_6_w1 + reg_key_slot_6_w1. + 0x84 + + + reg_key_slot_6_w1 + 0 + 31 + + + + + reg_key_slot_6_w2 + reg_key_slot_6_w2. + 0x88 + + + reg_key_slot_6_w2 + 0 + 31 + + + + + reg_key_slot_6_w3 + reg_key_slot_6_w3. + 0x8C + + + reg_key_slot_6_w3 + 0 + 31 + + + + + reg_key_slot_7_w0 + reg_key_slot_7_w0. + 0x90 + + + reg_key_slot_7_w0 + 0 + 31 + + + + + reg_key_slot_7_w1 + reg_key_slot_7_w1. + 0x94 + + + reg_key_slot_7_w1 + 0 + 31 + + + + + reg_key_slot_7_w2 + reg_key_slot_7_w2. + 0x98 + + + reg_key_slot_7_w2 + 0 + 31 + + + + + reg_key_slot_7_w3 + reg_key_slot_7_w3. + 0x9C + + + reg_key_slot_7_w3 + 0 + 31 + + + + + reg_key_slot_8_w0 + reg_key_slot_8_w0. + 0xA0 + + + reg_key_slot_8_w0 + 0 + 31 + + + + + reg_key_slot_8_w1 + reg_key_slot_8_w1. + 0xA4 + + + reg_key_slot_8_w1 + 0 + 31 + + + + + reg_key_slot_8_w2 + reg_key_slot_8_w2. + 0xA8 + + + reg_key_slot_8_w2 + 0 + 31 + + + + + reg_key_slot_8_w3 + reg_key_slot_8_w3. + 0xAC + + + reg_key_slot_8_w3 + 0 + 31 + + + + + reg_key_slot_9_w0 + reg_key_slot_9_w0. + 0xB0 + + + reg_key_slot_9_w0 + 0 + 31 + + + + + reg_key_slot_9_w1 + reg_key_slot_9_w1. + 0xB4 + + + reg_key_slot_9_w1 + 0 + 31 + + + + + reg_key_slot_9_w2 + reg_key_slot_9_w2. + 0xB8 + + + reg_key_slot_9_w2 + 0 + 31 + + + + + reg_key_slot_9_w3 + reg_key_slot_9_w3. + 0xBC + + + reg_key_slot_9_w3 + 0 + 31 + + + + + reg_key_slot_10_w0 + reg_key_slot_10_w0. + 0xC0 + + + + reg_key_slot_10_w1 + reg_key_slot_10_w1. + 0xC4 + + + + reg_key_slot_10_w2 + reg_key_slot_10_w2. + 0xC8 + + + + reg_key_slot_10_w3 + reg_key_slot_10_w3. + 0xCC + + + + reg_key_slot_11_w0 + reg_key_slot_11_w0. + 0xD0 + + + + reg_key_slot_11_w1 + reg_key_slot_11_w1. + 0xD4 + + + + reg_key_slot_11_w2 + reg_key_slot_11_w2. + 0xD8 + + + + reg_key_slot_11_w3 + reg_key_slot_11_w3. + 0xDC + + + + reg_data_1_lock + reg_data_1_lock. + 0xE0 + + + rd_lock_key_slot_9 + 29 + 29 + + + rd_lock_key_slot_8 + 28 + 28 + + + rd_lock_key_slot_7 + 27 + 27 + + + rd_lock_key_slot_6 + 26 + 26 + + + RESERVED_25_16 + 16 + 25 + + + wr_lock_key_slot_9 + 13 + 13 + + + wr_lock_key_slot_8 + 12 + 12 + + + wr_lock_key_slot_7 + 11 + 11 + + + wr_lock_key_slot_6 + 10 + 10 + + + RESERVED_9_0 + 0 + 9 + + + + + + + ef_ctrl + ef_ctrl. + 0x40007000 + ef_ctrl + 32 + read-write + + 0 + 0x1000 + registers + + + + ef_if_ctrl_0 + ef_if_ctrl_0. + 0x800 + + + ef_if_prot_code_cyc + 24 + 31 + + + ef_if_0_int_set + 22 + 22 + + + ef_if_0_int_clr + 21 + 21 + + + ef_if_0_int + 20 + 20 + + + ef_if_cyc_modify_lock + 19 + 19 + + + ef_if_auto_rd_en + 18 + 18 + + + ef_clk_sahb_data_gate + 17 + 17 + + + ef_if_por_dig + 16 + 16 + + + ef_if_prot_code_ctrl + 8 + 15 + + + ef_clk_sahb_data_sel + 7 + 7 + + + ef_if_0_cyc_modify + 6 + 6 + + + ef_if_0_manual_en + 5 + 5 + + + ef_if_0_trig + 4 + 4 + + + ef_if_0_rw + 3 + 3 + + + ef_if_0_busy + 2 + 2 + + + ef_if_0_autoload_done + 1 + 1 + + + ef_if_0_autoload_p1_done + 0 + 0 + + + + + ef_if_cyc_0 + ef_if_cyc_0. + 0x804 + + + ef_if_cyc_pd_cs_s + 24 + 31 + + + ef_if_cyc_cs + 18 + 23 + + + ef_if_cyc_rd_adr + 12 + 17 + + + ef_if_cyc_rd_dat + 6 + 11 + + + ef_if_cyc_rd_dmy + 0 + 5 + + + + + ef_if_cyc_1 + ef_if_cyc_1. + 0x808 + + + ef_if_cyc_pd_cs_h + 26 + 31 + + + ef_if_cyc_ps_cs + 20 + 25 + + + ef_if_cyc_wr_adr + 14 + 19 + + + ef_if_cyc_pp + 6 + 13 + + + ef_if_cyc_pi + 0 + 5 + + + + + ef_if_0_manual + ef_if_0_manual. + 0x80C + + + ef_if_prot_code_manual + 24 + 31 + + + ef_if_0_q + 16 + 23 + + + ef_if_csb + 15 + 15 + + + ef_if_load + 14 + 14 + + + ef_if_pgenb + 13 + 13 + + + ef_if_strobe + 12 + 12 + + + ef_if_ps + 11 + 11 + + + ef_if_pd + 10 + 10 + + + ef_if_a + 0 + 9 + + + + + ef_if_0_status + ef_if_0_status. + 0x810 + + + ef_if_0_status + 0 + 31 + + + + + ef_if_cfg_0 + ef_if_cfg_0. + 0x814 + + + ef_if_dbg_mode + 28 + 31 + + + ef_if_dbg_jtag_0_dis + 26 + 27 + + + ef_if_dbg_jtag_1_dis + 24 + 25 + + + ef_if_efuse_dbg_dis + 23 + 23 + + + ef_if_se_dbg_dis + 22 + 22 + + + ef_if_cpu_rst_dbg_dis + 21 + 21 + + + ef_if_cpu1_dis + 20 + 20 + + + ef_if_sf_dis + 19 + 19 + + + ef_if_cam_dis + 18 + 18 + + + ef_if_0_key_enc_en + 17 + 17 + + + ef_if_wifi_dis + 16 + 16 + + + ef_if_ble_dis + 15 + 15 + + + ef_if_sdu_dis + 14 + 14 + + + ef_if_sw_usage_1 + 12 + 13 + + + ef_if_boot_sel + 8 + 11 + + + ef_if_cpu0_enc_en + 7 + 7 + + + ef_if_cpu1_enc_en + 6 + 6 + + + ef_if_sboot_en + 4 + 5 + + + ef_if_sboot_sign_mode + 2 + 3 + + + ef_if_sf_aes_mode + 0 + 1 + + + + + ef_sw_cfg_0 + ef_sw_cfg_0. + 0x818 + + + ef_sw_dbg_mode + 28 + 31 + + + ef_sw_dbg_jtag_0_dis + 26 + 27 + + + ef_sw_dbg_jtag_1_dis + 24 + 25 + + + ef_sw_efuse_dbg_dis + 23 + 23 + + + ef_sw_se_dbg_dis + 22 + 22 + + + ef_sw_cpu_rst_dbg_dis + 21 + 21 + + + ef_sw_cpu1_dis + 20 + 20 + + + ef_sw_sf_dis + 19 + 19 + + + ef_sw_cam_dis + 18 + 18 + + + ef_sw_0_key_enc_en + 17 + 17 + + + ef_sw_wifi_dis + 16 + 16 + + + ef_sw_ble_dis + 15 + 15 + + + ef_sw_sdu_dis + 14 + 14 + + + ef_sw_sw_usage_1 + 12 + 13 + + + ef_sw_cpu0_enc_en + 7 + 7 + + + ef_sw_cpu1_enc_en + 6 + 6 + + + ef_sw_sboot_en + 4 + 5 + + + ef_sw_sboot_sign_mode + 2 + 3 + + + ef_sw_sf_aes_mode + 0 + 1 + + + + + ef_reserved + ef_reserved. + 0x81C + + + ef_reserved + 0 + 31 + + + + + ef_if_ana_trim_0 + ef_if_ana_trim_0. + 0x820 + + + ef_if_ana_trim_0 + 0 + 31 + + + + + ef_if_sw_usage_0 + ef_if_sw_usage_0. + 0x824 + + + ef_if_sw_usage_0 + 0 + 31 + + + + + ef_crc_ctrl_0 + ef_crc_ctrl_0. + 0xA00 + + + ef_crc_slp_n + 16 + 31 + + + ef_crc_lock + 11 + 11 + + + ef_crc_int_set + 10 + 10 + + + ef_crc_int_clr + 9 + 9 + + + ef_crc_int + 8 + 8 + + + ef_crc_din_endian + 7 + 7 + + + ef_crc_dout_endian + 6 + 6 + + + ef_crc_dout_inv_en + 5 + 5 + + + ef_crc_error + 4 + 4 + + + ef_crc_mode + 3 + 3 + + + ef_crc_en + 2 + 2 + + + ef_crc_trig + 1 + 1 + + + ef_crc_busy + 0 + 0 + + + + + ef_crc_ctrl_1 + ef_crc_ctrl_1. + 0xA04 + + + ef_crc_data_0_en + 0 + 31 + + + + + ef_crc_ctrl_2 + ef_crc_ctrl_2. + 0xA08 + + + ef_crc_data_1_en + 0 + 31 + + + + + ef_crc_ctrl_3 + ef_crc_ctrl_3. + 0xA0C + + + ef_crc_iv + 0 + 31 + + + + + ef_crc_ctrl_4 + ef_crc_ctrl_4. + 0xA10 + + + ef_crc_golden + 0 + 31 + + + + + ef_crc_ctrl_5 + ef_crc_ctrl_5. + 0xA14 + + + ef_crc_dout + 0 + 31 + + + + + + + cci + cci. + 0x40008000 + cci + 32 + read-write + + 0 + 0x1000 + registers + + + + cci_cfg + cci_cfg. + 0x0 + + + reg_mcci_clk_inv + 9 + 9 + + + reg_scci_clk_inv + 8 + 8 + + + cfg_cci1_pre_read + 7 + 7 + + + reg_div_m_cci_sclk + 5 + 6 + + + reg_m_cci_sclk_en + 4 + 4 + + + cci_mas_hw_mode + 3 + 3 + + + cci_mas_sel_cci2 + 2 + 2 + + + cci_slv_sel_cci2 + 1 + 1 + + + cci_en + 0 + 0 + + + + + cci_addr + cci_addr. + 0x4 + + + apb_cci_addr + 0 + 31 + + + + + cci_wdata + cci_wdata. + 0x8 + + + apb_cci_wdata + 0 + 31 + + + + + cci_rdata + cci_rdata. + 0xC + + + apb_cci_rdata + 0 + 31 + + + + + cci_ctl + cci_ctl. + 0x10 + + + ahb_state + 2 + 3 + + + cci_read_flag + 1 + 1 + + + cci_write_flag + 0 + 0 + + + + + + + l1c + l1c. + 0x40009000 + l1c + 32 + read-write + + 0 + 0x1000 + registers + + + + l1c_config + l1c_config. + 0x0 + + + wrap_dis + 26 + 26 + + + early_resp_dis + 25 + 25 + + + l1c_bmx_busy_option_dis + 24 + 24 + + + l1c_bmx_timeout_en + 20 + 23 + + + l1c_bmx_arb_mode + 16 + 17 + + + l1c_bmx_err_en + 15 + 15 + + + l1c_bypass + 14 + 14 + + + irom_2t_access + 12 + 12 + + + l1c_way_dis + 8 + 11 + + + l1c_invalid_done + 3 + 3 + + + l1c_invalid_en + 2 + 2 + + + l1c_cnt_en + 1 + 1 + + + l1c_cacheable + 0 + 0 + + + + + hit_cnt_lsb + hit_cnt_lsb. + 0x4 + + + hit_cnt_lsb + 0 + 31 + + + + + hit_cnt_msb + hit_cnt_msb. + 0x8 + + + hit_cnt_msb + 0 + 31 + + + + + miss_cnt + miss_cnt. + 0xC + + + miss_cnt + 0 + 31 + + + + + l1c_range + l1c_range. + 0x10 + + + + l1c_bmx_err_addr_en + l1c_bmx_err_addr_en. + 0x200 + + + l1c_hsel_option + 16 + 19 + + + l1c_bmx_err_tz + 5 + 5 + + + l1c_bmx_err_dec + 4 + 4 + + + l1c_bmx_err_addr_dis + 0 + 0 + + + + + l1c_bmx_err_addr + l1c_bmx_err_addr. + 0x204 + + + l1c_bmx_err_addr + 0 + 31 + + + + + irom1_misr_dataout_0 + irom1_misr_dataout_0. + 0x208 + + + irom1_misr_dataout_0 + 0 + 31 + + + + + irom1_misr_dataout_1 + irom1_misr_dataout_1. + 0x20C + + + + cpu_clk_gate + cpu_clk_gate. + 0x210 + + + force_e21_clock_on_2 + 2 + 2 + + + force_e21_clock_on_1 + 1 + 1 + + + force_e21_clock_on_0 + 0 + 0 + + + + + + + uart + uart. + 0x4000A000 + uart + 32 + read-write + + 0 + 0x1000 + registers + + + + utx_config + utx_config. + 0x0 + + + cr_utx_len + 16 + 31 + + + cr_utx_bit_cnt_p + 12 + 13 + + + cr_utx_bit_cnt_d + 8 + 10 + + + cr_utx_ir_inv + 7 + 7 + + + cr_utx_ir_en + 6 + 6 + + + cr_utx_prt_sel + 5 + 5 + + + cr_utx_prt_en + 4 + 4 + + + cr_utx_frm_en + 2 + 2 + + + cr_utx_cts_en + 1 + 1 + + + cr_utx_en + 0 + 0 + + + + + urx_config + urx_config. + 0x4 + + + cr_urx_len + 16 + 31 + + + cr_urx_deg_cnt + 12 + 15 + + + cr_urx_deg_en + 11 + 11 + + + cr_urx_bit_cnt_d + 8 + 10 + + + cr_urx_ir_inv + 7 + 7 + + + cr_urx_ir_en + 6 + 6 + + + cr_urx_prt_sel + 5 + 5 + + + cr_urx_prt_en + 4 + 4 + + + cr_urx_abr_en + 3 + 3 + + + cr_urx_rts_sw_val + 2 + 2 + + + cr_urx_rts_sw_mode + 1 + 1 + + + cr_urx_en + 0 + 0 + + + + + uart_bit_prd + uart_bit_prd. + 0x8 + + + cr_urx_bit_prd + 16 + 31 + + + cr_utx_bit_prd + 0 + 15 + + + + + data_config + data_config. + 0xC + + + cr_uart_bit_inv + 0 + 0 + + + + + utx_ir_position + utx_ir_position. + 0x10 + + + cr_utx_ir_pos_p + 16 + 31 + + + cr_utx_ir_pos_s + 0 + 15 + + + + + urx_ir_position + urx_ir_position. + 0x14 + + + cr_urx_ir_pos_s + 0 + 15 + + + + + urx_rto_timer + urx_rto_timer. + 0x18 + + + cr_urx_rto_value + 0 + 7 + + + + + uart_int_sts + UART interrupt status + 0x20 + + + urx_fer_int + 7 + 7 + + + utx_fer_int + 6 + 6 + + + urx_pce_int + 5 + 5 + + + urx_rto_int + 4 + 4 + + + urx_fifo_int + 3 + 3 + + + utx_fifo_int + 2 + 2 + + + urx_end_int + 1 + 1 + + + utx_end_int + 0 + 0 + + + + + uart_int_mask + UART interrupt mask + 0x24 + + + cr_urx_fer_mask + 7 + 7 + + + cr_utx_fer_mask + 6 + 6 + + + cr_urx_pce_mask + 5 + 5 + + + cr_urx_rto_mask + 4 + 4 + + + cr_urx_fifo_mask + 3 + 3 + + + cr_utx_fifo_mask + 2 + 2 + + + cr_urx_end_mask + 1 + 1 + + + cr_utx_end_mask + 0 + 0 + + + + + uart_int_clear + UART interrupt clear + 0x28 + + + rsvd_7 + 7 + 7 + + + rsvd_6 + 6 + 6 + + + cr_urx_pce_clr + 5 + 5 + + + cr_urx_rto_clr + 4 + 4 + + + rsvd_3 + 3 + 3 + + + rsvd_2 + 2 + 2 + + + cr_urx_end_clr + 1 + 1 + + + cr_utx_end_clr + 0 + 0 + + + + + uart_int_en + UART interrupt enable + 0x2C + + + cr_urx_fer_en + 7 + 7 + + + cr_utx_fer_en + 6 + 6 + + + cr_urx_pce_en + 5 + 5 + + + cr_urx_rto_en + 4 + 4 + + + cr_urx_fifo_en + 3 + 3 + + + cr_utx_fifo_en + 2 + 2 + + + cr_urx_end_en + 1 + 1 + + + cr_utx_end_en + 0 + 0 + + + + + uart_status + uart_status. + 0x30 + + + sts_urx_bus_busy + 1 + 1 + + + sts_utx_bus_busy + 0 + 0 + + + + + sts_urx_abr_prd + sts_urx_abr_prd. + 0x34 + + + sts_urx_abr_prd_0x55 + 16 + 31 + + + sts_urx_abr_prd_start + 0 + 15 + + + + + uart_fifo_config_0 + uart_fifo_config_0. + 0x80 + + + rx_fifo_underflow + 7 + 7 + + + rx_fifo_overflow + 6 + 6 + + + tx_fifo_underflow + 5 + 5 + + + tx_fifo_overflow + 4 + 4 + + + rx_fifo_clr + 3 + 3 + + + tx_fifo_clr + 2 + 2 + + + uart_dma_rx_en + 1 + 1 + + + uart_dma_tx_en + 0 + 0 + + + + + uart_fifo_config_1 + uart_fifo_config_1. + 0x84 + + + rx_fifo_th + 24 + 28 + + + tx_fifo_th + 16 + 20 + + + rx_fifo_cnt + 8 + 13 + + + tx_fifo_cnt + 0 + 5 + + + + + uart_fifo_wdata + uart_fifo_wdata. + 0x88 + + + uart_fifo_wdata + 0 + 7 + + + + + uart_fifo_rdata + uart_fifo_rdata. + 0x8C + + + uart_fifo_rdata + 0 + 7 + + + + + + + spi + spi. + 0x4000A200 + spi + 32 + read-write + + 0 + 0x1000 + registers + + + + spi_config + spi_config. + 0x0 + + + cr_spi_deg_cnt + 12 + 15 + + + cr_spi_deg_en + 11 + 11 + + + cr_spi_m_cont_en + 9 + 9 + + + cr_spi_rxd_ignr_en + 8 + 8 + + + cr_spi_byte_inv + 7 + 7 + + + cr_spi_bit_inv + 6 + 6 + + + cr_spi_sclk_ph + 5 + 5 + + + cr_spi_sclk_pol + 4 + 4 + + + cr_spi_frame_size + 2 + 3 + + + cr_spi_s_en + 1 + 1 + + + cr_spi_m_en + 0 + 0 + + + + + spi_int_sts + spi_int_sts. + 0x4 + + + cr_spi_fer_en + 29 + 29 + + + cr_spi_txu_en + 28 + 28 + + + cr_spi_sto_en + 27 + 27 + + + cr_spi_rxf_en + 26 + 26 + + + cr_spi_txf_en + 25 + 25 + + + cr_spi_end_en + 24 + 24 + + + rsvd_21 + 21 + 21 + + + cr_spi_txu_clr + 20 + 20 + + + cr_spi_sto_clr + 19 + 19 + + + rsvd_18 + 18 + 18 + + + rsvd_17 + 17 + 17 + + + cr_spi_end_clr + 16 + 16 + + + cr_spi_fer_mask + 13 + 13 + + + cr_spi_txu_mask + 12 + 12 + + + cr_spi_sto_mask + 11 + 11 + + + cr_spi_rxf_mask + 10 + 10 + + + cr_spi_txf_mask + 9 + 9 + + + cr_spi_end_mask + 8 + 8 + + + spi_fer_int + 5 + 5 + + + spi_txu_int + 4 + 4 + + + spi_sto_int + 3 + 3 + + + spi_rxf_int + 2 + 2 + + + spi_txf_int + 1 + 1 + + + spi_end_int + 0 + 0 + + + + + spi_bus_busy + spi_bus_busy. + 0x8 + + + sts_spi_bus_busy + 0 + 0 + + + + + spi_prd_0 + spi_prd_0. + 0x10 + + + cr_spi_prd_d_ph_1 + 24 + 31 + + + cr_spi_prd_d_ph_0 + 16 + 23 + + + cr_spi_prd_p + 8 + 15 + + + cr_spi_prd_s + 0 + 7 + + + + + spi_prd_1 + spi_prd_1. + 0x14 + + + cr_spi_prd_i + 0 + 7 + + + + + spi_rxd_ignr + spi_rxd_ignr. + 0x18 + + + cr_spi_rxd_ignr_s + 16 + 20 + + + cr_spi_rxd_ignr_p + 0 + 4 + + + + + spi_sto_value + spi_sto_value. + 0x1C + + + cr_spi_sto_value + 0 + 11 + + + + + spi_fifo_config_0 + spi_fifo_config_0. + 0x80 + + + rx_fifo_underflow + 7 + 7 + + + rx_fifo_overflow + 6 + 6 + + + tx_fifo_underflow + 5 + 5 + + + tx_fifo_overflow + 4 + 4 + + + rx_fifo_clr + 3 + 3 + + + tx_fifo_clr + 2 + 2 + + + spi_dma_rx_en + 1 + 1 + + + spi_dma_tx_en + 0 + 0 + + + + + spi_fifo_config_1 + spi_fifo_config_1. + 0x84 + + + rx_fifo_th + 24 + 25 + + + tx_fifo_th + 16 + 17 + + + rx_fifo_cnt + 8 + 10 + + + tx_fifo_cnt + 0 + 2 + + + + + spi_fifo_wdata + spi_fifo_wdata. + 0x88 + + + spi_fifo_wdata + 0 + 31 + + + + + spi_fifo_rdata + spi_fifo_rdata. + 0x8C + + + spi_fifo_rdata + 0 + 31 + + + + + + + i2c + i2c. + 0x4000A300 + i2c + 32 + read-write + + 0 + 0x1000 + registers + + + + i2c_config + i2c_config. + 0x0 + + + cr_i2c_deg_cnt + 28 + 31 + + + cr_i2c_pkt_len + 16 + 23 + + + cr_i2c_slv_addr + 8 + 14 + + + cr_i2c_sub_addr_bc + 5 + 6 + + + cr_i2c_sub_addr_en + 4 + 4 + + + cr_i2c_scl_sync_en + 3 + 3 + + + cr_i2c_deg_en + 2 + 2 + + + cr_i2c_pkt_dir + 1 + 1 + + + cr_i2c_m_en + 0 + 0 + + + + + i2c_int_sts + i2c_int_sts. + 0x4 + + + cr_i2c_fer_en + 29 + 29 + + + cr_i2c_arb_en + 28 + 28 + + + cr_i2c_nak_en + 27 + 27 + + + cr_i2c_rxf_en + 26 + 26 + + + cr_i2c_txf_en + 25 + 25 + + + cr_i2c_end_en + 24 + 24 + + + rsvd_21 + 21 + 21 + + + cr_i2c_arb_clr + 20 + 20 + + + cr_i2c_nak_clr + 19 + 19 + + + rsvd_18 + 18 + 18 + + + rsvd_17 + 17 + 17 + + + cr_i2c_end_clr + 16 + 16 + + + cr_i2c_fer_mask + 13 + 13 + + + cr_i2c_arb_mask + 12 + 12 + + + cr_i2c_nak_mask + 11 + 11 + + + cr_i2c_rxf_mask + 10 + 10 + + + cr_i2c_txf_mask + 9 + 9 + + + cr_i2c_end_mask + 8 + 8 + + + i2c_fer_int + 5 + 5 + + + i2c_arb_int + 4 + 4 + + + i2c_nak_int + 3 + 3 + + + i2c_rxf_int + 2 + 2 + + + i2c_txf_int + 1 + 1 + + + i2c_end_int + 0 + 0 + + + + + i2c_sub_addr + i2c_sub_addr. + 0x8 + + + cr_i2c_sub_addr_b3 + 24 + 31 + + + cr_i2c_sub_addr_b2 + 16 + 23 + + + cr_i2c_sub_addr_b1 + 8 + 15 + + + cr_i2c_sub_addr_b0 + 0 + 7 + + + + + i2c_bus_busy + i2c_bus_busy. + 0xC + + + cr_i2c_bus_busy_clr + 1 + 1 + + + sts_i2c_bus_busy + 0 + 0 + + + + + i2c_prd_start + i2c_prd_start. + 0x10 + + + cr_i2c_prd_s_ph_3 + 24 + 31 + + + cr_i2c_prd_s_ph_2 + 16 + 23 + + + cr_i2c_prd_s_ph_1 + 8 + 15 + + + cr_i2c_prd_s_ph_0 + 0 + 7 + + + + + i2c_prd_stop + i2c_prd_stop. + 0x14 + + + cr_i2c_prd_p_ph_3 + 24 + 31 + + + cr_i2c_prd_p_ph_2 + 16 + 23 + + + cr_i2c_prd_p_ph_1 + 8 + 15 + + + cr_i2c_prd_p_ph_0 + 0 + 7 + + + + + i2c_prd_data + i2c_prd_data. + 0x18 + + + cr_i2c_prd_d_ph_3 + 24 + 31 + + + cr_i2c_prd_d_ph_2 + 16 + 23 + + + cr_i2c_prd_d_ph_1 + 8 + 15 + + + cr_i2c_prd_d_ph_0 + 0 + 7 + + + + + i2c_fifo_config_0 + i2c_fifo_config_0. + 0x80 + + + rx_fifo_underflow + 7 + 7 + + + rx_fifo_overflow + 6 + 6 + + + tx_fifo_underflow + 5 + 5 + + + tx_fifo_overflow + 4 + 4 + + + rx_fifo_clr + 3 + 3 + + + tx_fifo_clr + 2 + 2 + + + i2c_dma_rx_en + 1 + 1 + + + i2c_dma_tx_en + 0 + 0 + + + + + i2c_fifo_config_1 + i2c_fifo_config_1. + 0x84 + + + rx_fifo_th + 24 + 24 + + + tx_fifo_th + 16 + 16 + + + rx_fifo_cnt + 8 + 9 + + + tx_fifo_cnt + 0 + 1 + + + + + i2c_fifo_wdata + i2c_fifo_wdata. + 0x88 + + + i2c_fifo_wdata + 0 + 31 + + + + + i2c_fifo_rdata + i2c_fifo_rdata. + 0x8C + + + i2c_fifo_rdata + 0 + 31 + + + + + + + pwm + pwm. + 0x4000A400 + pwm + 32 + read-write + + 0 + 0x1000 + registers + + + + pwm_int_config + pwm_int_config. + 0x0 + + + pwm_int_clear + 8 + 13 + + + pwm_interrupt_sts + 0 + 5 + + + + + pwm0_clkdiv + pwm0_clkdiv. + 0x20 + + + pwm_clk_div + 0 + 15 + + + + + pwm0_thre1 + pwm0_thre1. + 0x24 + + + pwm_thre1 + 0 + 15 + + + + + pwm0_thre2 + pwm0_thre2. + 0x28 + + + pwm_thre2 + 0 + 15 + + + + + pwm0_period + pwm0_period. + 0x2C + + + pwm_period + 0 + 15 + + + + + pwm0_config + pwm0_config. + 0x30 + + + pwm_sts_top + 7 + 7 + + + pwm_stop_en + 6 + 6 + + + pwm_sw_mode + 5 + 5 + + + pwm_sw_force_val + 4 + 4 + + + pwm_stop_mode + 3 + 3 + + + pwm_out_inv + 2 + 2 + + + reg_clk_sel + 0 + 1 + + + + + pwm0_interrupt + pwm0_interrupt. + 0x34 + + + pwm_int_enable + 16 + 16 + + + pwm_int_period_cnt + 0 + 15 + + + + + pwm1_clkdiv + pwm1_clkdiv. + 0x40 + + + pwm_clk_div + 0 + 15 + + + + + pwm1_thre1 + pwm1_thre1. + 0x44 + + + pwm_thre1 + 0 + 15 + + + + + pwm1_thre2 + pwm1_thre2. + 0x48 + + + pwm_thre2 + 0 + 15 + + + + + pwm1_period + pwm1_period. + 0x4C + + + pwm_period + 0 + 15 + + + + + pwm1_config + pwm1_config. + 0x50 + + + pwm_sts_top + 7 + 7 + + + pwm_stop_en + 6 + 6 + + + pwm_sw_mode + 5 + 5 + + + pwm_sw_force_val + 4 + 4 + + + pwm_stop_mode + 3 + 3 + + + pwm_out_inv + 2 + 2 + + + reg_clk_sel + 0 + 1 + + + + + pwm1_interrupt + pwm1_interrupt. + 0x54 + + + pwm_int_enable + 16 + 16 + + + pwm_int_period_cnt + 0 + 15 + + + + + pwm2_clkdiv + pwm2_clkdiv. + 0x60 + + + pwm_clk_div + 0 + 15 + + + + + pwm2_thre1 + pwm2_thre1. + 0x64 + + + pwm_thre1 + 0 + 15 + + + + + pwm2_thre2 + pwm2_thre2. + 0x68 + + + pwm_thre2 + 0 + 15 + + + + + pwm2_period + pwm2_period. + 0x6C + + + pwm_period + 0 + 15 + + + + + pwm2_config + pwm2_config. + 0x70 + + + pwm_sts_top + 7 + 7 + + + pwm_stop_en + 6 + 6 + + + pwm_sw_mode + 5 + 5 + + + pwm_sw_force_val + 4 + 4 + + + pwm_stop_mode + 3 + 3 + + + pwm_out_inv + 2 + 2 + + + reg_clk_sel + 0 + 1 + + + + + pwm2_interrupt + pwm2_interrupt. + 0x74 + + + pwm_int_enable + 16 + 16 + + + pwm_int_period_cnt + 0 + 15 + + + + + pwm3_clkdiv + pwm3_clkdiv. + 0x80 + + + pwm_clk_div + 0 + 15 + + + + + pwm3_thre1 + pwm3_thre1. + 0x84 + + + pwm_thre1 + 0 + 15 + + + + + pwm3_thre2 + pwm3_thre2. + 0x88 + + + pwm_thre2 + 0 + 15 + + + + + pwm3_period + pwm3_period. + 0x8C + + + pwm_period + 0 + 15 + + + + + pwm3_config + pwm3_config. + 0x90 + + + pwm_sts_top + 7 + 7 + + + pwm_stop_en + 6 + 6 + + + pwm_sw_mode + 5 + 5 + + + pwm_sw_force_val + 4 + 4 + + + pwm_stop_mode + 3 + 3 + + + pwm_out_inv + 2 + 2 + + + reg_clk_sel + 0 + 1 + + + + + pwm3_interrupt + pwm3_interrupt. + 0x94 + + + pwm_int_enable + 16 + 16 + + + pwm_int_period_cnt + 0 + 15 + + + + + pwm4_clkdiv + pwm4_clkdiv. + 0xA0 + + + pwm_clk_div + 0 + 15 + + + + + pwm4_thre1 + pwm4_thre1. + 0xA4 + + + pwm_thre1 + 0 + 15 + + + + + pwm4_thre2 + pwm4_thre2. + 0xA8 + + + pwm_thre2 + 0 + 15 + + + + + pwm4_period + pwm4_period. + 0xAC + + + pwm_period + 0 + 15 + + + + + pwm4_config + pwm4_config. + 0xB0 + + + pwm_sts_top + 7 + 7 + + + pwm_stop_en + 6 + 6 + + + pwm_sw_mode + 5 + 5 + + + pwm_sw_force_val + 4 + 4 + + + pwm_stop_mode + 3 + 3 + + + pwm_out_inv + 2 + 2 + + + reg_clk_sel + 0 + 1 + + + + + pwm4_interrupt + pwm4_interrupt. + 0xB4 + + + pwm_int_enable + 16 + 16 + + + pwm_int_period_cnt + 0 + 15 + + + + + + + timer + timer. + 0x4000A500 + timer + 32 + read-write + + 0 + 0x1000 + registers + + + + TCCR + TCCR. + 0x0 + + + cs_wdt + 8 + 9 + + + RESERVED_7 + 7 + 7 + + + cs_2 + 5 + 6 + + + RESERVED_4 + 4 + 4 + + + cs_1 + 2 + 3 + + + + + TMR2_0 + TMR2_0. + 0x10 + + + tmr + 0 + 31 + + + + + TMR2_1 + TMR2_1. + 0x14 + + + tmr + 0 + 31 + + + + + TMR2_2 + TMR2_2. + 0x18 + + + tmr + 0 + 31 + + + + + TMR3_0 + TMR3_0. + 0x1C + + + tmr + 0 + 31 + + + + + TMR3_1 + TMR3_1. + 0x20 + + + tmr + 0 + 31 + + + + + TMR3_2 + TMR3_2. + 0x24 + + + tmr + 0 + 31 + + + + + TCR2 + TCR2. + 0x2C + + + tcr + 0 + 31 + + + + + TCR3 + TCR3. + 0x30 + + + tcr3_counter + 0 + 31 + + + + + TMSR2 + TMSR2. + 0x38 + + + tmsr_2 + 2 + 2 + + + tmsr_1 + 1 + 1 + + + tmsr_0 + 0 + 0 + + + + + TMSR3 + TMSR3. + 0x3C + + + tmsr_2 + 2 + 2 + + + tmsr_1 + 1 + 1 + + + tmsr_0 + 0 + 0 + + + + + TIER2 + TIER2. + 0x44 + + + tier_2 + 2 + 2 + + + tier_1 + 1 + 1 + + + tier_0 + 0 + 0 + + + + + TIER3 + TIER3. + 0x48 + + + tier_2 + 2 + 2 + + + tier_1 + 1 + 1 + + + tier_0 + 0 + 0 + + + + + TPLVR2 + TPLVR2. + 0x50 + + + tplvr + 0 + 31 + + + + + TPLVR3 + TPLVR3. + 0x54 + + + tplvr + 0 + 31 + + + + + TPLCR2 + TPLCR2. + 0x5C + + + tplcr + 0 + 1 + + + + + TPLCR3 + TPLCR3. + 0x60 + + + tplcr + 0 + 1 + + + + + WMER + WMER. + 0x64 + + + wrie + 1 + 1 + + + we + 0 + 0 + + + + + WMR + WMR. + 0x68 + + + wmr + 0 + 15 + + + + + WVR + WVR. + 0x6C + + + wvr + 0 + 15 + + + + + WSR + WSR. + 0x70 + + + wts + 0 + 0 + + + + + TICR2 + TICR2. + 0x78 + + + tclr_2 + 2 + 2 + + + tclr_1 + 1 + 1 + + + tclr_0 + 0 + 0 + + + + + TICR3 + TICR3. + 0x7C + + + tclr_2 + 2 + 2 + + + tclr_1 + 1 + 1 + + + tclr_0 + 0 + 0 + + + + + WICR + WICR. + 0x80 + + + wiclr + 0 + 0 + + + + + TCER + TCER. + 0x84 + + + timer3_en + 2 + 2 + + + timer2_en + 1 + 1 + + + + + TCMR + TCMR. + 0x88 + + + timer3_mode + 2 + 2 + + + timer2_mode + 1 + 1 + + + + + TILR2 + TILR2. + 0x90 + + + tilr_2 + 2 + 2 + + + tilr_1 + 1 + 1 + + + tilr_0 + 0 + 0 + + + + + TILR3 + TILR3. + 0x94 + + + tilr_2 + 2 + 2 + + + tilr_1 + 1 + 1 + + + tilr_0 + 0 + 0 + + + + + WCR + WCR. + 0x98 + + + wcr + 0 + 0 + + + + + WFAR + WFAR. + 0x9C + + + wfar + 0 + 15 + + + + + WSAR + WSAR. + 0xA0 + + + wsar + 0 + 15 + + + + + TCVWR2 + TCVWR2. + 0xA8 + + + tcvwr + 0 + 31 + + + + + TCVWR3 + TCVWR3. + 0xAC + + + tcvwr + 0 + 31 + + + + + TCVSYN2 + TCVSYN2. + 0xB4 + + + tcvsyn2 + 0 + 31 + + + + + TCVSYN3 + TCVSYN3. + 0xB8 + + + tcvsyn3 + 0 + 31 + + + + + TCDR + TCDR. + 0xBC + + + wcdr + 24 + 31 + + + tcdr3 + 16 + 23 + + + tcdr2 + 8 + 15 + + + + + + + ir + ir. + 0x4000A600 + ir + 32 + read-write + + 0 + 0x1000 + registers + + + + irtx_config + irtx_config. + 0x0 + + + cr_irtx_data_num + 12 + 17 + + + cr_irtx_tail_hl_inv + 11 + 11 + + + cr_irtx_tail_en + 10 + 10 + + + cr_irtx_head_hl_inv + 9 + 9 + + + cr_irtx_head_en + 8 + 8 + + + cr_irtx_logic1_hl_inv + 6 + 6 + + + cr_irtx_logic0_hl_inv + 5 + 5 + + + cr_irtx_data_en + 4 + 4 + + + cr_irtx_swm_en + 3 + 3 + + + cr_irtx_mod_en + 2 + 2 + + + cr_irtx_out_inv + 1 + 1 + + + cr_irtx_en + 0 + 0 + + + + + irtx_int_sts + irtx_int_sts. + 0x4 + + + cr_irtx_end_en + 24 + 24 + + + cr_irtx_end_clr + 16 + 16 + + + cr_irtx_end_mask + 8 + 8 + + + irtx_end_int + 0 + 0 + + + + + irtx_data_word0 + irtx_data_word0. + 0x8 + + + cr_irtx_data_word0 + 0 + 31 + + + + + irtx_data_word1 + irtx_data_word1. + 0xC + + + cr_irtx_data_word1 + 0 + 31 + + + + + irtx_pulse_width + irtx_pulse_width. + 0x10 + + + cr_irtx_mod_ph1_w + 24 + 31 + + + cr_irtx_mod_ph0_w + 16 + 23 + + + cr_irtx_pw_unit + 0 + 11 + + + + + irtx_pw + irtx_pw. + 0x14 + + + cr_irtx_tail_ph1_w + 28 + 31 + + + cr_irtx_tail_ph0_w + 24 + 27 + + + cr_irtx_head_ph1_w + 20 + 23 + + + cr_irtx_head_ph0_w + 16 + 19 + + + cr_irtx_logic1_ph1_w + 12 + 15 + + + cr_irtx_logic1_ph0_w + 8 + 11 + + + cr_irtx_logic0_ph1_w + 4 + 7 + + + cr_irtx_logic0_ph0_w + 0 + 3 + + + + + irtx_swm_pw_0 + irtx_swm_pw_0. + 0x40 + + + cr_irtx_swm_pw_0 + 0 + 31 + + + + + irtx_swm_pw_1 + irtx_swm_pw_1. + 0x44 + + + cr_irtx_swm_pw_1 + 0 + 31 + + + + + irtx_swm_pw_2 + irtx_swm_pw_2. + 0x48 + + + cr_irtx_swm_pw_2 + 0 + 31 + + + + + irtx_swm_pw_3 + irtx_swm_pw_3. + 0x4C + + + cr_irtx_swm_pw_3 + 0 + 31 + + + + + irtx_swm_pw_4 + irtx_swm_pw_4. + 0x50 + + + cr_irtx_swm_pw_4 + 0 + 31 + + + + + irtx_swm_pw_5 + irtx_swm_pw_5. + 0x54 + + + cr_irtx_swm_pw_5 + 0 + 31 + + + + + irtx_swm_pw_6 + irtx_swm_pw_6. + 0x58 + + + cr_irtx_swm_pw_6 + 0 + 31 + + + + + irtx_swm_pw_7 + irtx_swm_pw_7. + 0x5C + + + cr_irtx_swm_pw_7 + 0 + 31 + + + + + irrx_config + irrx_config. + 0x80 + + + cr_irrx_deg_cnt + 8 + 11 + + + cr_irrx_deg_en + 4 + 4 + + + cr_irrx_mode + 2 + 3 + + + cr_irrx_in_inv + 1 + 1 + + + cr_irrx_en + 0 + 0 + + + + + irrx_int_sts + irrx_int_sts. + 0x84 + + + cr_irrx_end_en + 24 + 24 + + + cr_irrx_end_clr + 16 + 16 + + + cr_irrx_end_mask + 8 + 8 + + + irrx_end_int + 0 + 0 + + + + + irrx_pw_config + irrx_pw_config. + 0x88 + + + cr_irrx_end_th + 16 + 31 + + + cr_irrx_data_th + 0 + 15 + + + + + irrx_data_count + irrx_data_count. + 0x90 + + + sts_irrx_data_cnt + 0 + 6 + + + + + irrx_data_word0 + irrx_data_word0. + 0x94 + + + sts_irrx_data_word0 + 0 + 31 + + + + + irrx_data_word1 + irrx_data_word1. + 0x98 + + + sts_irrx_data_word1 + 0 + 31 + + + + + irrx_swm_fifo_config_0 + irrx_swm_fifo_config_0. + 0xC0 + + + rx_fifo_cnt + 4 + 10 + + + rx_fifo_underflow + 3 + 3 + + + rx_fifo_overflow + 2 + 2 + + + rx_fifo_clr + 0 + 0 + + + + + irrx_swm_fifo_rdata + irrx_swm_fifo_rdata. + 0xC4 + + + rx_fifo_rdata + 0 + 15 + + + + + + + cks + cks. + 0x4000A000 + cks + 32 + read-write + + 0 + 0x1000 + registers + + + + cks_config + cks_config. + 0x0 + + + cr_cks_byte_swap + 1 + 1 + + + cr_cks_clr + 0 + 0 + + + + + data_in + data_in. + 0x4 + + + data_in + 0 + 7 + + + + + cks_out + cks_out. + 0x8 + + + cks_out + 0 + 15 + + + + + + + sf_ctrl + sf_ctrl. + 0x4000B000 + sf_ctrl + 32 + read-write + + 0 + 0x1000 + registers + + + + sf_ctrl_0 + sf_ctrl_0. + 0x0 + + + sf_id + 24 + 31 + + + sf_aes_iv_endian + 23 + 23 + + + sf_aes_key_endian + 22 + 22 + + + sf_aes_ctr_plus_en + 21 + 21 + + + sf_aes_dout_endian + 20 + 20 + + + sf_aes_dly_mode + 19 + 19 + + + sf_if_int_set + 18 + 18 + + + sf_if_int_clr + 17 + 17 + + + sf_if_int + 16 + 16 + + + sf_if_read_dly_en + 11 + 11 + + + sf_if_read_dly_n + 8 + 10 + + + sf_clk_sahb_sram_sel + 5 + 5 + + + sf_clk_out_inv_sel + 4 + 4 + + + sf_clk_out_gate_en + 3 + 3 + + + sf_clk_sf_rx_inv_sel + 2 + 2 + + + + + sf_ctrl_1 + sf_ctrl_1. + 0x4 + + + sf_ahb2sram_en + 31 + 31 + + + sf_ahb2sif_en + 30 + 30 + + + sf_if_en + 29 + 29 + + + sf_if_fn_sel + 28 + 28 + + + sf_ahb2sif_stop + 27 + 27 + + + sf_ahb2sif_stopped + 26 + 26 + + + sf_if_reg_wp + 25 + 25 + + + sf_if_reg_hold + 24 + 24 + + + sf_if_0_ack_lat + 20 + 22 + + + sf_if_sr_int_set + 18 + 18 + + + sf_if_sr_int_en + 17 + 17 + + + sf_if_sr_int + 16 + 16 + + + sf_if_sr_pat + 8 + 15 + + + sf_if_sr_pat_mask + 0 + 7 + + + + + sf_if_sahb_0 + sf_if_sahb_0. + 0x8 + + + sf_if_0_qpi_mode_en + 31 + 31 + + + sf_if_0_spi_mode + 28 + 30 + + + sf_if_0_cmd_en + 27 + 27 + + + sf_if_0_adr_en + 26 + 26 + + + sf_if_0_dmy_en + 25 + 25 + + + sf_if_0_dat_en + 24 + 24 + + + sf_if_0_dat_rw + 23 + 23 + + + sf_if_0_cmd_byte + 20 + 22 + + + sf_if_0_adr_byte + 17 + 19 + + + sf_if_0_dmy_byte + 12 + 16 + + + sf_if_0_dat_byte + 2 + 11 + + + sf_if_0_trig + 1 + 1 + + + sf_if_busy + 0 + 0 + + + + + sf_if_sahb_1 + sf_if_sahb_1. + 0xC + + + sf_if_0_cmd_buf_0 + 0 + 31 + + + + + sf_if_sahb_2 + sf_if_sahb_2. + 0x10 + + + sf_if_0_cmd_buf_1 + 0 + 31 + + + + + sf_if_iahb_0 + sf_if_iahb_0. + 0x14 + + + sf_if_1_qpi_mode_en + 31 + 31 + + + sf_if_1_spi_mode + 28 + 30 + + + sf_if_1_cmd_en + 27 + 27 + + + sf_if_1_adr_en + 26 + 26 + + + sf_if_1_dmy_en + 25 + 25 + + + sf_if_1_dat_en + 24 + 24 + + + sf_if_1_dat_rw + 23 + 23 + + + sf_if_1_cmd_byte + 20 + 22 + + + sf_if_1_adr_byte + 17 + 19 + + + sf_if_1_dmy_byte + 12 + 16 + + + + + sf_if_iahb_1 + sf_if_iahb_1. + 0x18 + + + sf_if_1_cmd_buf_0 + 0 + 31 + + + + + sf_if_iahb_2 + sf_if_iahb_2. + 0x1C + + + sf_if_1_cmd_buf_1 + 0 + 31 + + + + + sf_if_status_0 + sf_if_status_0. + 0x20 + + + sf_if_status_0 + 0 + 31 + + + + + sf_if_status_1 + sf_if_status_1. + 0x24 + + + sf_if_status_1 + 0 + 31 + + + + + sf_aes + sf_aes. + 0x28 + + + sf_aes_status + 5 + 31 + + + sf_aes_pref_busy + 4 + 4 + + + sf_aes_pref_trig + 3 + 3 + + + sf_aes_mode + 1 + 2 + + + sf_aes_en + 0 + 0 + + + + + sf_ahb2sif_status + sf_ahb2sif_status. + 0x2C + + + sf_ahb2sif_status + 0 + 31 + + + + + sf_if_io_dly_0 + sf_if_io_dly_0. + 0x30 + + + sf_dqs_do_dly_sel + 30 + 31 + + + sf_dqs_di_dly_sel + 28 + 29 + + + sf_dqs_oe_dly_sel + 26 + 27 + + + sf_clk_out_dly_sel + 8 + 9 + + + sf_cs_dly_sel + 0 + 1 + + + + + sf_if_io_dly_1 + sf_if_io_dly_1. + 0x34 + + + sf_io_0_do_dly_sel + 16 + 17 + + + sf_io_0_di_dly_sel + 8 + 9 + + + sf_io_0_oe_dly_sel + 0 + 1 + + + + + sf_if_io_dly_2 + sf_if_io_dly_2. + 0x38 + + + sf_io_1_do_dly_sel + 16 + 17 + + + sf_io_1_di_dly_sel + 8 + 9 + + + sf_io_1_oe_dly_sel + 0 + 1 + + + + + sf_if_io_dly_3 + sf_if_io_dly_3. + 0x3C + + + sf_io_2_do_dly_sel + 16 + 17 + + + sf_io_2_di_dly_sel + 8 + 9 + + + sf_io_2_oe_dly_sel + 0 + 1 + + + + + sf_if_io_dly_4 + sf_if_io_dly_4. + 0x40 + + + sf_io_3_do_dly_sel + 16 + 17 + + + sf_io_3_di_dly_sel + 8 + 9 + + + sf_io_3_oe_dly_sel + 0 + 1 + + + + + sf_reserved + sf_reserved. + 0x44 + + + sf_reserved + 0 + 31 + + + + + sf2_if_io_dly_0 + sf2_if_io_dly_0. + 0x48 + + + sf2_dqs_do_dly_sel + 30 + 31 + + + sf2_dqs_di_dly_sel + 28 + 29 + + + sf2_dqs_oe_dly_sel + 26 + 27 + + + sf2_clk_out_dly_sel + 8 + 9 + + + sf2_cs_dly_sel + 0 + 1 + + + + + sf2_if_io_dly_1 + sf2_if_io_dly_1. + 0x4C + + + sf2_io_0_do_dly_sel + 16 + 17 + + + sf2_io_0_di_dly_sel + 8 + 9 + + + sf2_io_0_oe_dly_sel + 0 + 1 + + + + + sf2_if_io_dly_2 + sf2_if_io_dly_2. + 0x50 + + + sf2_io_1_do_dly_sel + 16 + 17 + + + sf2_io_1_di_dly_sel + 8 + 9 + + + sf2_io_1_oe_dly_sel + 0 + 1 + + + + + sf2_if_io_dly_3 + sf2_if_io_dly_3. + 0x54 + + + sf2_io_2_do_dly_sel + 16 + 17 + + + sf2_io_2_di_dly_sel + 8 + 9 + + + sf2_io_2_oe_dly_sel + 0 + 1 + + + + + sf2_if_io_dly_4 + sf2_if_io_dly_4. + 0x58 + + + sf2_io_3_do_dly_sel + 16 + 17 + + + sf2_io_3_di_dly_sel + 8 + 9 + + + sf2_io_3_oe_dly_sel + 0 + 1 + + + + + sf3_if_io_dly_0 + sf3_if_io_dly_0. + 0x5C + + + sf3_dqs_do_dly_sel + 30 + 31 + + + sf3_dqs_di_dly_sel + 28 + 29 + + + sf3_dqs_oe_dly_sel + 26 + 27 + + + sf3_clk_out_dly_sel + 8 + 9 + + + sf3_cs_dly_sel + 0 + 1 + + + + + sf3_if_io_dly_1 + sf3_if_io_dly_1. + 0x60 + + + sf3_io_0_do_dly_sel + 16 + 17 + + + sf3_io_0_di_dly_sel + 8 + 9 + + + sf3_io_0_oe_dly_sel + 0 + 1 + + + + + sf3_if_io_dly_2 + sf3_if_io_dly_2. + 0x64 + + + sf3_io_1_do_dly_sel + 16 + 17 + + + sf3_io_1_di_dly_sel + 8 + 9 + + + sf3_io_1_oe_dly_sel + 0 + 1 + + + + + sf3_if_io_dly_3 + sf3_if_io_dly_3. + 0x68 + + + sf3_io_2_do_dly_sel + 16 + 17 + + + sf3_io_2_di_dly_sel + 8 + 9 + + + sf3_io_2_oe_dly_sel + 0 + 1 + + + + + sf3_if_io_dly_4 + sf3_if_io_dly_4. + 0x6C + + + sf3_io_3_do_dly_sel + 16 + 17 + + + sf3_io_3_di_dly_sel + 8 + 9 + + + sf3_io_3_oe_dly_sel + 0 + 1 + + + + + sf_ctrl_2 + sf_ctrl_2. + 0x70 + + + sf_if_dqs_en + 5 + 5 + + + sf_if_dtr_en + 4 + 4 + + + sf_if_pad_sel_lock + 3 + 3 + + + sf_if_pad_sel + 0 + 1 + + + + + sf_ctrl_3 + sf_ctrl_3. + 0x74 + + + sf_if_1_ack_lat + 29 + 31 + + + sf_cmds_wrap_mode + 10 + 10 + + + sf_cmds_wrap_q_ini + 9 + 9 + + + sf_cmds_bt_en + 8 + 8 + + + sf_cmds_bt_dly + 5 + 7 + + + sf_cmds_en + 4 + 4 + + + sf_cmds_wrap_len + 0 + 3 + + + + + sf_if_iahb_3 + sf_if_iahb_3. + 0x78 + + + sf_if_2_qpi_mode_en + 31 + 31 + + + sf_if_2_spi_mode + 28 + 30 + + + sf_if_2_cmd_en + 27 + 27 + + + sf_if_2_adr_en + 26 + 26 + + + sf_if_2_dmy_en + 25 + 25 + + + sf_if_2_dat_en + 24 + 24 + + + sf_if_2_dat_rw + 23 + 23 + + + sf_if_2_cmd_byte + 20 + 22 + + + sf_if_2_adr_byte + 17 + 19 + + + sf_if_2_dmy_byte + 12 + 16 + + + + + sf_if_iahb_4 + sf_if_iahb_4. + 0x7C + + + sf_if_2_cmd_buf_0 + 0 + 31 + + + + + sf_if_iahb_5 + sf_if_iahb_5. + 0x80 + + + sf_if_2_cmd_buf_1 + 0 + 31 + + + + + sf_if_iahb_6 + sf_if_iahb_6. + 0x84 + + + sf_if_3_qpi_mode_en + 31 + 31 + + + sf_if_3_spi_mode + 28 + 30 + + + sf_if_3_cmd_byte + 20 + 22 + + + + + sf_if_iahb_7 + sf_if_iahb_7. + 0x88 + + + sf_if_3_cmd_buf_0 + 0 + 31 + + + + + sf_ctrl_prot_en_rd + sf_ctrl_prot_en_rd. + 0x100 + + + sf_dbg_dis + 31 + 31 + + + sf_if_0_trig_wr_lock + 30 + 30 + + + sf_ctrl_id1_en_rd + 2 + 2 + + + sf_ctrl_id0_en_rd + 1 + 1 + + + sf_ctrl_prot_en_rd + 0 + 0 + + + + + sf_ctrl_prot_en + sf_ctrl_prot_en. + 0x104 + + + sf_ctrl_id1_en + 2 + 2 + + + sf_ctrl_id0_en + 1 + 1 + + + sf_ctrl_prot_en + 0 + 0 + + + + + sf_aes_key_r0_0 + sf_aes_key_r0_0. + 0x200 + + + sf_aes_key_r0_0 + 0 + 31 + + + + + sf_aes_key_r0_1 + sf_aes_key_r0_1. + 0x204 + + + sf_aes_key_r0_1 + 0 + 31 + + + + + sf_aes_key_r0_2 + sf_aes_key_r0_2. + 0x208 + + + sf_aes_key_r0_2 + 0 + 31 + + + + + sf_aes_key_r0_3 + sf_aes_key_r0_3. + 0x20C + + + sf_aes_key_r0_3 + 0 + 31 + + + + + sf_aes_key_r0_4 + sf_aes_key_r0_4. + 0x210 + + + sf_aes_key_r0_4 + 0 + 31 + + + + + sf_aes_key_r0_5 + sf_aes_key_r0_5. + 0x214 + + + sf_aes_key_r0_5 + 0 + 31 + + + + + sf_aes_key_r0_6 + sf_aes_key_r0_6. + 0x218 + + + sf_aes_key_r0_6 + 0 + 31 + + + + + sf_aes_key_r0_7 + sf_aes_key_r0_7. + 0x21C + + + sf_aes_key_r0_7 + 0 + 31 + + + + + sf_aes_iv_r0_w0 + sf_aes_iv_r0_w0. + 0x220 + + + sf_aes_iv_r0_w0 + 0 + 31 + + + + + sf_aes_iv_r0_w1 + sf_aes_iv_r0_w1. + 0x224 + + + sf_aes_iv_r0_w1 + 0 + 31 + + + + + sf_aes_iv_r0_w2 + sf_aes_iv_r0_w2. + 0x228 + + + sf_aes_iv_r0_w2 + 0 + 31 + + + + + sf_aes_iv_r0_w3 + sf_aes_iv_r0_w3. + 0x22C + + + sf_aes_iv_r0_w3 + 0 + 31 + + + + + sf_aes_cfg_r0 + sf_aes_cfg_r0. + 0x230 + + + sf_aes_region_r0_lock + 31 + 31 + + + sf_aes_region_r0_en + 30 + 30 + + + sf_aes_region_r0_hw_key_en + 29 + 29 + + + sf_aes_region_r0_start + 14 + 27 + + + sf_aes_region_r0_end + 0 + 13 + + + + + sf_aes_key_r1_0 + sf_aes_key_r1_0. + 0x300 + + + sf_aes_key_r1_0 + 0 + 31 + + + + + sf_aes_key_r1_1 + sf_aes_key_r1_1. + 0x304 + + + sf_aes_key_r1_1 + 0 + 31 + + + + + sf_aes_key_r1_2 + sf_aes_key_r1_2. + 0x308 + + + sf_aes_key_r1_2 + 0 + 31 + + + + + sf_aes_key_r1_3 + sf_aes_key_r1_3. + 0x30C + + + sf_aes_key_r1_3 + 0 + 31 + + + + + sf_aes_key_r1_4 + sf_aes_key_r1_4. + 0x310 + + + sf_aes_key_r1_4 + 0 + 31 + + + + + sf_aes_key_r1_5 + sf_aes_key_r1_5. + 0x314 + + + sf_aes_key_r1_5 + 0 + 31 + + + + + sf_aes_key_r1_6 + sf_aes_key_r1_6. + 0x318 + + + sf_aes_key_r1_6 + 0 + 31 + + + + + sf_aes_key_r1_7 + sf_aes_key_r1_7. + 0x31C + + + sf_aes_key_r1_7 + 0 + 31 + + + + + sf_aes_iv_r1_w0 + sf_aes_iv_r1_w0. + 0x320 + + + sf_aes_iv_r1_w0 + 0 + 31 + + + + + sf_aes_iv_r1_w1 + sf_aes_iv_r1_w1. + 0x324 + + + sf_aes_iv_r1_w1 + 0 + 31 + + + + + sf_aes_iv_r1_w2 + sf_aes_iv_r1_w2. + 0x328 + + + sf_aes_iv_r1_w2 + 0 + 31 + + + + + sf_aes_iv_r1_w3 + sf_aes_iv_r1_w3. + 0x32C + + + sf_aes_iv_r1_w3 + 0 + 31 + + + + + sf_aes_r1 + sf_aes_r1. + 0x330 + + + sf_aes_r1_lock + 31 + 31 + + + sf_aes_r1_en + 30 + 30 + + + sf_aes_r1_hw_key_en + 29 + 29 + + + sf_aes_r1_start + 14 + 27 + + + sf_aes_r1_end + 0 + 13 + + + + + sf_aes_key_r2_0 + sf_aes_key_r2_0. + 0x400 + + + sf_aes_key_r2_0 + 0 + 31 + + + + + sf_aes_key_r2_1 + sf_aes_key_r2_1. + 0x404 + + + sf_aes_key_r2_1 + 0 + 31 + + + + + sf_aes_key_r2_2 + sf_aes_key_r2_2. + 0x408 + + + sf_aes_key_r2_2 + 0 + 31 + + + + + sf_aes_key_r2_3 + sf_aes_key_r2_3. + 0x40C + + + sf_aes_key_r2_3 + 0 + 31 + + + + + sf_aes_key_r2_4 + sf_aes_key_r2_4. + 0x410 + + + sf_aes_key_r2_4 + 0 + 31 + + + + + sf_aes_key_r2_5 + sf_aes_key_r2_5. + 0x414 + + + sf_aes_key_r2_5 + 0 + 31 + + + + + sf_aes_key_r2_6 + sf_aes_key_r2_6. + 0x418 + + + sf_aes_key_r2_6 + 0 + 31 + + + + + sf_aes_key_r2_7 + sf_aes_key_r2_7. + 0x41C + + + sf_aes_key_r2_7 + 0 + 31 + + + + + sf_aes_iv_r2_w0 + sf_aes_iv_r2_w0. + 0x420 + + + sf_aes_iv_r2_w0 + 0 + 31 + + + + + sf_aes_iv_r2_w1 + sf_aes_iv_r2_w1. + 0x424 + + + sf_aes_iv_r2_w1 + 0 + 31 + + + + + sf_aes_iv_r2_w2 + sf_aes_iv_r2_w2. + 0x428 + + + sf_aes_iv_r2_w2 + 0 + 31 + + + + + sf_aes_iv_r2_w3 + sf_aes_iv_r2_w3. + 0x42C + + + sf_aes_iv_r2_w3 + 0 + 31 + + + + + sf_aes_r2 + sf_aes_r2. + 0x430 + + + sf_aes_r2_lock + 31 + 31 + + + sf_aes_r2_en + 30 + 30 + + + sf_aes_r2_hw_key_en + 29 + 29 + + + sf_aes_r2_start + 14 + 27 + + + sf_aes_r2_end + 0 + 13 + + + + + sf_id0_offset + sf_id0_offset. + 0x434 + + + sf_id0_offset + 0 + 23 + + + + + sf_id1_offset + sf_id1_offset. + 0x438 + + + sf_id1_offset + 0 + 23 + + + + + + + dma + dma. + 0x4000C000 + dma + 32 + read-write + + 0 + 0x1000 + registers + + + + DMA_IntStatus + DMA_IntStatus. + 0x0 + + + IntStatus + 0 + 7 + + + + + DMA_IntTCStatus + DMA_IntTCStatus. + 0x4 + + + IntTCStatus + 0 + 7 + + + + + DMA_IntTCClear + DMA_IntTCClear. + 0x8 + + + IntTCClear + 0 + 7 + + + + + DMA_IntErrorStatus + DMA_IntErrorStatus. + 0xC + + + IntErrorStatus + 0 + 7 + + + + + DMA_IntErrClr + DMA_IntErrClr. + 0x10 + + + IntErrClr + 0 + 7 + + + + + DMA_RawIntTCStatus + DMA_RawIntTCStatus. + 0x14 + + + RawIntTCStatus + 0 + 7 + + + + + DMA_RawIntErrorStatus + DMA_RawIntErrorStatus. + 0x18 + + + RawIntErrorStatus + 0 + 7 + + + + + DMA_EnbldChns + DMA_EnbldChns. + 0x1C + + + EnabledChannels + 0 + 7 + + + + + DMA_SoftBReq + DMA_SoftBReq. + 0x20 + + + SoftBReq + 0 + 31 + + + + + DMA_SoftSReq + DMA_SoftSReq. + 0x24 + + + SoftSReq + 0 + 31 + + + + + DMA_SoftLBReq + DMA_SoftLBReq. + 0x28 + + + SoftLBReq + 0 + 31 + + + + + DMA_SoftLSReq + DMA_SoftLSReq. + 0x2C + + + SoftLSReq + 0 + 31 + + + + + DMA_Top_Config + DMA_Top_Config. + 0x30 + + + M + 1 + 1 + + + E + 0 + 0 + + + + + DMA_Sync + DMA_Sync. + 0x34 + + + DMA_Sync + 0 + 31 + + + + + DMA_C0SrcAddr + DMA_C0SrcAddr. + 0x100 + + + SrcAddr + 0 + 31 + + + + + DMA_C0DstAddr + DMA_C0DstAddr. + 0x104 + + + DstAddr + 0 + 31 + + + + + DMA_C0LLI + DMA_C0LLI. + 0x108 + + + LLI + 0 + 31 + + + + + DMA_C0Control + DMA_C0Control. + 0x10C + + + I + 31 + 31 + + + Prot + 28 + 30 + + + DI + 27 + 27 + + + SI + 26 + 26 + + + SLargerD + 24 + 24 + + + DWidth + 21 + 23 + + + SWidth + 18 + 20 + + + DBSize + 15 + 17 + + + SBSize + 12 + 14 + + + TransferSize + 0 + 11 + + + + + DMA_C0Config + DMA_C0Config. + 0x110 + + + LLICounter + 20 + 29 + + + H + 18 + 18 + + + A + 17 + 17 + + + L + 16 + 16 + + + ITC + 15 + 15 + + + IE + 14 + 14 + + + FlowCntrl + 11 + 13 + + + DstPeripheral + 6 + 10 + + + SrcPeripheral + 1 + 5 + + + E + 0 + 0 + + + + + DMA_C1SrcAddr + DMA_C1SrcAddr. + 0x200 + + + SrcAddr + 0 + 31 + + + + + DMA_C1DstAddr + DMA_C1DstAddr. + 0x204 + + + DstAddr + 0 + 31 + + + + + DMA_C1LLI + DMA_C1LLI. + 0x208 + + + LLI + 2 + 31 + + + + + DMA_C1Control + DMA_C1Control. + 0x20C + + + I + 31 + 31 + + + Prot + 28 + 30 + + + DI + 27 + 27 + + + SI + 26 + 26 + + + DWidth + 21 + 23 + + + SWidth + 18 + 20 + + + DBSize + 15 + 17 + + + SBSize + 12 + 14 + + + TransferSize + 0 + 11 + + + + + DMA_C1Config + DMA_C1Config. + 0x210 + + + H + 18 + 18 + + + A + 17 + 17 + + + L + 16 + 16 + + + ITC + 15 + 15 + + + IE + 14 + 14 + + + FlowCntrl + 11 + 13 + + + DstPeripheral + 6 + 10 + + + SrcPeripheral + 1 + 5 + + + E + 0 + 0 + + + + + DMA_C2SrcAddr + DMA_C2SrcAddr. + 0x300 + + + SrcAddr + 0 + 31 + + + + + DMA_C2DstAddr + DMA_C2DstAddr. + 0x304 + + + DstAddr + 0 + 31 + + + + + DMA_C2LLI + DMA_C2LLI. + 0x308 + + + LLI + 2 + 31 + + + + + DMA_C2Control + DMA_C2Control. + 0x30C + + + I + 31 + 31 + + + Prot + 28 + 30 + + + DI + 27 + 27 + + + SI + 26 + 26 + + + DWidth + 21 + 23 + + + SWidth + 18 + 20 + + + DBSize + 15 + 17 + + + SBSize + 12 + 14 + + + TransferSize + 0 + 11 + + + + + DMA_C2Config + DMA_C2Config. + 0x310 + + + H + 18 + 18 + + + A + 17 + 17 + + + L + 16 + 16 + + + ITC + 15 + 15 + + + IE + 14 + 14 + + + FlowCntrl + 11 + 13 + + + DstPeripheral + 6 + 10 + + + SrcPeripheral + 1 + 5 + + + E + 0 + 0 + + + + + DMA_C3SrcAddr + DMA_C3SrcAddr. + 0x400 + + + SrcAddr + 0 + 31 + + + + + DMA_C3DstAddr + DMA_C3DstAddr. + 0x404 + + + DstAddr + 0 + 31 + + + + + DMA_C3LLI + DMA_C3LLI. + 0x408 + + + LLI + 2 + 31 + + + + + DMA_C3Control + DMA_C3Control. + 0x40C + + + I + 31 + 31 + + + Prot + 28 + 30 + + + DI + 27 + 27 + + + SI + 26 + 26 + + + DWidth + 21 + 23 + + + SWidth + 18 + 20 + + + DBSize + 15 + 17 + + + SBSize + 12 + 14 + + + TransferSize + 0 + 11 + + + + + DMA_C3Config + DMA_C3Config. + 0x410 + + + H + 18 + 18 + + + A + 17 + 17 + + + L + 16 + 16 + + + ITC + 15 + 15 + + + IE + 14 + 14 + + + FlowCntrl + 11 + 13 + + + DstPeripheral + 6 + 10 + + + SrcPeripheral + 1 + 5 + + + E + 0 + 0 + + + + + + + pds + pds. + 0x4000E000 + pds + 32 + read-write + + 0 + 0x1000 + registers + + + + PDS_CTL + PDS_CTL. + 0x0 + + + cr_pds_ctrl_pll + 30 + 31 + + + cr_pds_ctrl_rf + 28 + 29 + + + cr_pds_ldo_vol + 24 + 27 + + + cr_pds_pd_ldo11 + 22 + 22 + + + cr_np_wfi_mask + 21 + 21 + + + cr_pds_ldo_vsel_en + 18 + 18 + + + cr_pds_rc32m_off_dis + 17 + 17 + + + cr_pds_rst_soc_en + 16 + 16 + + + cr_pds_soc_enb_force_on + 15 + 15 + + + cr_pds_pd_xtal + 14 + 14 + + + cr_pds_pwr_off + 13 + 13 + + + cr_pds_wait_xtal_rdy + 12 + 12 + + + cr_pds_iso_en + 11 + 11 + + + cr_pds_mem_stby + 9 + 9 + + + cr_pds_gate_clk + 8 + 8 + + + cr_pds_pd_bg_sys + 5 + 5 + + + cr_pds_pd_dcdc18 + 4 + 4 + + + cr_wifi_pds_save_state + 3 + 3 + + + cr_xtal_force_off + 2 + 2 + + + cr_sleep_forever + 1 + 1 + + + pds_start_ps + 0 + 0 + + + + + PDS_TIME1 + PDS_TIME1. + 0x4 + + + cr_sleep_duration + 0 + 31 + + + + + PDS_INT + PDS_INT. + 0xC + + + cr_pds_int_clr + 16 + 16 + + + cr_pds_pll_done_int_mask + 11 + 11 + + + cr_pds_rf_done_int_mask + 10 + 10 + + + cr_pds_irq_in_dis + 9 + 9 + + + cr_pds_wake_int_mask + 8 + 8 + + + ro_pds_pll_done_int + 3 + 3 + + + ro_pds_rf_done_int + 2 + 2 + + + ro_pds_irq_in + 1 + 1 + + + ro_pds_wake_int + 0 + 0 + + + + + PDS_CTL2 + PDS_CTL2. + 0x10 + + + cr_pds_force_wb_gate_clk + 18 + 18 + + + cr_pds_force_np_gate_clk + 16 + 16 + + + cr_pds_force_wb_mem_stby + 14 + 14 + + + cr_pds_force_np_mem_stby + 12 + 12 + + + cr_pds_force_wb_pds_rst + 10 + 10 + + + cr_pds_force_np_pds_rst + 8 + 8 + + + cr_pds_force_wb_iso_en + 6 + 6 + + + cr_pds_force_np_iso_en + 4 + 4 + + + cr_pds_force_wb_pwr_off + 2 + 2 + + + cr_pds_force_np_pwr_off + 0 + 0 + + + + + PDS_CTL3 + PDS_CTL3. + 0x14 + + + cr_pds_misc_iso_en + 30 + 30 + + + cr_pds_wb_iso_en + 27 + 27 + + + cr_pds_np_iso_en + 24 + 24 + + + cr_pds_force_misc_gate_clk + 13 + 13 + + + cr_pds_force_misc_mem_stby + 10 + 10 + + + cr_pds_force_misc_pds_rst + 7 + 7 + + + cr_pds_force_misc_iso_en + 4 + 4 + + + cr_pds_force_misc_pwr_off + 1 + 1 + + + + + PDS_CTL4 + PDS_CTL4. + 0x18 + + + cr_pds_misc_gate_clk + 27 + 27 + + + cr_pds_misc_mem_stby + 26 + 26 + + + cr_pds_misc_reset + 25 + 25 + + + cr_pds_misc_pwr_off + 24 + 24 + + + cr_pds_wb_gate_clk + 15 + 15 + + + cr_pds_wb_mem_stby + 14 + 14 + + + cr_pds_wb_reset + 13 + 13 + + + cr_pds_wb_pwr_off + 12 + 12 + + + cr_pds_np_gate_clk + 3 + 3 + + + cr_pds_np_mem_stby + 2 + 2 + + + cr_pds_np_reset + 1 + 1 + + + cr_pds_np_pwr_off + 0 + 0 + + + + + pds_stat + pds_stat. + 0x1C + + + ro_pds_pll_state + 16 + 17 + + + ro_pds_rf_state + 8 + 11 + + + ro_pds_state + 0 + 3 + + + + + pds_ram1 + pds_ram1. + 0x20 + + + cr_np_sram_pwr + 0 + 7 + + + + + rc32m_ctrl0 + rc32m_ctrl0. + 0x300 + + + rc32m_code_fr_ext + 22 + 29 + + + rc32m_pd + 21 + 21 + + + rc32m_cal_en + 20 + 20 + + + rc32m_ext_code_en + 19 + 19 + + + rc32m_refclk_half + 18 + 18 + + + rc32m_allow_cal + 17 + 17 + + + rc32m_dig_code_fr_cal + 6 + 13 + + + rc32m_cal_precharge + 5 + 5 + + + rc32m_cal_div + 3 + 4 + + + rc32m_cal_inprogress + 2 + 2 + + + rc32m_rdy + 1 + 1 + + + rc32m_cal_done + 0 + 0 + + + + + rc32m_ctrl1 + rc32m_ctrl1. + 0x304 + + + rc32m_reserved + 24 + 31 + + + rc32m_clk_force_on + 4 + 4 + + + rc32m_clk_inv + 3 + 3 + + + rc32m_clk_soft_rst + 2 + 2 + + + rc32m_soft_rst + 1 + 1 + + + rc32m_test_en + 0 + 0 + + + + + pu_rst_clkpll + pu_rst_clkpll. + 0x400 + + + pu_clkpll + 10 + 10 + + + pu_clkpll_sfreg + 9 + 9 + + + clkpll_pu_cp + 8 + 8 + + + clkpll_pu_pfd + 7 + 7 + + + clkpll_pu_clamp_op + 6 + 6 + + + clkpll_pu_fbdv + 5 + 5 + + + clkpll_pu_postdiv + 4 + 4 + + + clkpll_reset_refdiv + 3 + 3 + + + clkpll_reset_fbdv + 2 + 2 + + + clkpll_reset_postdiv + 1 + 1 + + + clkpll_sdm_reset + 0 + 0 + + + + + clkpll_top_ctrl + clkpll_top_ctrl. + 0x404 + + + clkpll_vg13_sel + 24 + 25 + + + clkpll_vg11_sel + 20 + 21 + + + clkpll_refclk_sel + 16 + 16 + + + clkpll_xtal_rc32m_sel + 12 + 12 + + + clkpll_refdiv_ratio + 8 + 11 + + + clkpll_postdiv + 0 + 6 + + + + + clkpll_cp + clkpll_cp. + 0x408 + + + clkpll_cp_opamp_en + 10 + 10 + + + clkpll_cp_startup_en + 9 + 9 + + + clkpll_int_frac_sw + 8 + 8 + + + clkpll_icp_1u + 6 + 7 + + + clkpll_icp_5u + 4 + 5 + + + clkpll_sel_cp_bias + 0 + 0 + + + + + clkpll_rz + clkpll_rz. + 0x40C + + + clkpll_rz + 16 + 18 + + + clkpll_cz + 14 + 15 + + + clkpll_c3 + 12 + 13 + + + clkpll_r4_short + 8 + 8 + + + clkpll_r4 + 4 + 5 + + + clkpll_c4_en + 0 + 0 + + + + + clkpll_fbdv + clkpll_fbdv. + 0x410 + + + clkpll_sel_fb_clk + 2 + 3 + + + clkpll_sel_sample_clk + 0 + 1 + + + + + clkpll_vco + clkpll_vco. + 0x414 + + + clkpll_shrtr + 3 + 3 + + + clkpll_vco_speed + 0 + 2 + + + + + clkpll_sdm + clkpll_sdm. + 0x418 + + + clkpll_sdm_bypass + 29 + 29 + + + clkpll_sdm_flag + 28 + 28 + + + clkpll_dither_sel + 24 + 25 + + + clkpll_sdmin + 0 + 23 + + + + + clkpll_output_en + clkpll_output_en. + 0x41C + + + clkpll_en_div2_480m + 9 + 9 + + + clkpll_en_32m + 8 + 8 + + + clkpll_en_48m + 7 + 7 + + + clkpll_en_80m + 6 + 6 + + + clkpll_en_96m + 5 + 5 + + + clkpll_en_120m + 4 + 4 + + + clkpll_en_160m + 3 + 3 + + + clkpll_en_192m + 2 + 2 + + + clkpll_en_240m + 1 + 1 + + + clkpll_en_480m + 0 + 0 + + + + + + + HBN + HBN. + 0x4000F000 + HBN + 32 + read-write + + 0 + 0x1000 + registers + + + + HBN_CTL + HBN_CTL. + 0x0 + + + hbn_state + 28 + 31 + + + sram_slp + 27 + 27 + + + sram_slp_option + 26 + 26 + + + pwr_on_option + 25 + 25 + + + rtc_dly_option + 24 + 24 + + + pu_dcdc18_aon + 23 + 23 + + + hbn_ldo11_aon_vout_sel + 19 + 22 + + + hbn_ldo11_rt_vout_sel + 15 + 18 + + + hbn_dis_pwr_off_ldo11_rt + 14 + 14 + + + hbn_dis_pwr_off_ldo11 + 13 + 13 + + + sw_rst + 12 + 12 + + + pwrdn_hbn_rtc + 11 + 11 + + + pwrdn_hbn_core + 9 + 9 + + + trap_mode + 8 + 8 + + + hbn_mode + 7 + 7 + + + rtc_ctl + 0 + 6 + + + + + HBN_TIME_L + HBN_TIME_L. + 0x4 + + + hbn_time_l + 0 + 31 + + + + + HBN_TIME_H + HBN_TIME_H. + 0x8 + + + hbn_time_h + 0 + 7 + + + + + RTC_TIME_L + RTC_TIME_L. + 0xC + + + rtc_time_latch_l + 0 + 31 + + + + + RTC_TIME_H + RTC_TIME_H. + 0x10 + + + rtc_time_latch + 31 + 31 + + + rtc_time_latch_h + 0 + 7 + + + + + HBN_IRQ_MODE + HBN_IRQ_MODE. + 0x14 + + + pin_wakeup_en + 27 + 27 + + + pin_wakeup_sel + 24 + 26 + + + irq_acomp1_en + 22 + 23 + + + irq_acomp0_en + 20 + 21 + + + irq_bor_en + 18 + 18 + + + reg_en_hw_pu_pd + 16 + 16 + + + reg_aon_pad_ie_smt + 8 + 8 + + + hbn_pin_wakeup_mask + 3 + 4 + + + hbn_pin_wakeup_mode + 0 + 2 + + + + + HBN_IRQ_STAT + HBN_IRQ_STAT. + 0x18 + + + irq_stat + 0 + 31 + + + + + HBN_IRQ_CLR + HBN_IRQ_CLR. + 0x1C + + + irq_clr + 0 + 31 + + + + + HBN_PIR_CFG + HBN_PIR_CFG. + 0x20 + + + gpadc_nosync + 9 + 9 + + + gpadc_cgen + 8 + 8 + + + pir_en + 7 + 7 + + + pir_dis + 4 + 5 + + + pir_lpf_sel + 2 + 2 + + + pir_hpf_sel + 0 + 1 + + + + + HBN_PIR_VTH + HBN_PIR_VTH. + 0x24 + + + pir_vth + 0 + 13 + + + + + HBN_PIR_INTERVAL + HBN_PIR_INTERVAL. + 0x28 + + + pir_interval + 0 + 11 + + + + + HBN_BOR_CFG + HBN_BOR_CFG. + 0x2C + + + r_bor_out + 3 + 3 + + + pu_bor + 2 + 2 + + + bor_vth + 1 + 1 + + + bor_sel + 0 + 0 + + + + + HBN_GLB + HBN_GLB. + 0x30 + + + sw_ldo11_aon_vout_sel + 28 + 31 + + + sw_ldo11_rt_vout_sel + 24 + 27 + + + sw_ldo11soc_vout_sel_aon + 16 + 19 + + + hbn_pu_rc32k + 5 + 5 + + + hbn_f32k_sel + 3 + 4 + + + hbn_uart_clk_sel + 2 + 2 + + + hbn_root_clk_sel + 0 + 1 + + + + + HBN_SRAM + HBN_SRAM. + 0x34 + + + retram_slp + 7 + 7 + + + retram_ret + 6 + 6 + + + + + HBN_RSV0 + HBN_RSV0. + 0x100 + + + HBN_RSV0 + 0 + 31 + + + + + HBN_RSV1 + HBN_RSV1. + 0x104 + + + HBN_RSV1 + 0 + 31 + + + + + HBN_RSV2 + HBN_RSV2. + 0x108 + + + HBN_RSV2 + 0 + 31 + + + + + HBN_RSV3 + HBN_RSV3. + 0x10C + + + HBN_RSV3 + 0 + 31 + + + + + rc32k_ctrl0 + rc32k_ctrl0. + 0x200 + + + rc32k_code_fr_ext + 22 + 31 + + + rc32k_cal_en + 20 + 20 + + + rc32k_ext_code_en + 19 + 19 + + + rc32k_allow_cal + 18 + 18 + + + rc32k_vref_dly + 16 + 17 + + + rc32k_dig_code_fr_cal + 6 + 15 + + + rc32k_cal_precharge + 5 + 5 + + + rc32k_cal_div + 3 + 4 + + + rc32k_cal_inprogress + 2 + 2 + + + rc32k_rdy + 1 + 1 + + + rc32k_cal_done + 0 + 0 + + + + + xtal32k + xtal32k. + 0x204 + + + pu_xtal32k + 19 + 19 + + + pu_xtal32k_buf + 18 + 18 + + + xtal32k_ac_cap_short + 17 + 17 + + + xtal32k_capbank + 11 + 16 + + + xtal32k_inv_stre + 9 + 10 + + + xtal32k_otf_short + 8 + 8 + + + xtal32k_outbuf_stre + 7 + 7 + + + xtal32k_reg + 5 + 6 + + + xtal32k_amp_ctrl + 3 + 4 + + + xtal32k_ext_sel + 2 + 2 + + + + + + + AON + AON. + 0x4000F000 + AON + 32 + read-write + + 0 + 0x1000 + registers + + + + aon + aon. + 0x800 + + + sw_pu_ldo11_rt + 22 + 22 + + + ldo11_rt_pulldown_sel + 21 + 21 + + + ldo11_rt_pulldown + 20 + 20 + + + pu_aon_dc_tbuf + 12 + 12 + + + aon_resv + 0 + 7 + + + + + aon_common + aon_common. + 0x804 + + + ten_cip_misc_aon + 20 + 20 + + + ten_mbg_aon + 19 + 19 + + + dten_xtal_aon + 18 + 18 + + + ten_xtal_aon + 17 + 17 + + + ten_ldo15rf_aon + 16 + 16 + + + ten_bg_sys_aon + 12 + 12 + + + ten_dcdc18_1_aon + 11 + 11 + + + ten_dcdc18_0_aon + 10 + 10 + + + ten_ldo11soc_aon + 9 + 9 + + + ten_vddcore_aon + 8 + 8 + + + ten_xtal32k + 6 + 6 + + + dten_xtal32k + 5 + 5 + + + ten_aon + 4 + 4 + + + tmux_aon + 0 + 2 + + + + + aon_misc + aon_misc. + 0x808 + + + sw_wb_en_aon + 1 + 1 + + + sw_soc_en_aon + 0 + 0 + + + + + bg_sys_top + bg_sys_top. + 0x810 + + + bg_sys_start_ctrl_aon + 12 + 12 + + + pu_bg_sys_aon + 8 + 8 + + + pmip_resv + 0 + 7 + + + + + dcdc18_top_0 + dcdc18_top_0. + 0x814 + + + dcdc18_rdy_aon + 31 + 31 + + + dcdc18_sstart_time_aon + 28 + 29 + + + dcdc18_osc_inhibit_t2_aon + 27 + 27 + + + dcdc18_slow_osc_aon + 26 + 26 + + + dcdc18_stop_osc_aon + 25 + 25 + + + dcdc18_slope_curr_sel_aon + 20 + 24 + + + dcdc18_osc_freq_trim_aon + 16 + 19 + + + dcdc18_osc_2m_mode_aon + 12 + 12 + + + dcdc18_vpfm_aon + 8 + 11 + + + dcdc18_vout_sel_aon + 1 + 5 + + + + + dcdc18_top_1 + dcdc18_top_1. + 0x818 + + + dcdc18_pulldown_aon + 29 + 29 + + + dcdc18_en_antiring_aon + 28 + 28 + + + dcdc18_cfb_sel_aon + 24 + 27 + + + dcdc18_chf_sel_aon + 20 + 23 + + + dcdc18_rc_sel_aon + 16 + 19 + + + dcdc18_nonoverlap_td_aon + 8 + 12 + + + dcdc18_zvs_td_opt_aon + 4 + 6 + + + dcdc18_cs_delay_aon + 1 + 3 + + + dcdc18_force_cs_zvs_aon + 0 + 0 + + + + + ldo11soc_and_dctest + ldo11soc_and_dctest. + 0x81C + + + pmip_dc_tp_out_en_aon + 31 + 31 + + + pu_vddcore_misc_aon + 30 + 30 + + + ldo11soc_power_good_aon + 29 + 29 + + + ldo11soc_rdy_aon + 28 + 28 + + + ldo11soc_cc_aon + 24 + 25 + + + ldo11soc_vth_sel_aon + 12 + 13 + + + ldo11soc_pulldown_sel_aon + 11 + 11 + + + ldo11soc_pulldown_aon + 10 + 10 + + + ldo11soc_sstart_delay_aon + 8 + 9 + + + ldo11soc_sstart_sel_aon + 4 + 4 + + + pu_ldo11soc_aon + 0 + 0 + + + + + psw_irrcv + psw_irrcv. + 0x820 + + + pu_ir_psw_aon + 0 + 0 + + + + + rf_top_aon + rf_top_aon. + 0x880 + + + ldo15rf_bypass_aon + 28 + 28 + + + ldo15rf_cc_aon + 24 + 25 + + + ldo15rf_vout_sel_aon + 16 + 18 + + + ldo15rf_pulldown_sel_aon + 13 + 13 + + + ldo15rf_pulldown_aon + 12 + 12 + + + ldo15rf_sstart_delay_aon + 9 + 10 + + + ldo15rf_sstart_sel_aon + 8 + 8 + + + pu_xtal_aon + 5 + 5 + + + pu_xtal_buf_aon + 4 + 4 + + + pu_sfreg_aon + 2 + 2 + + + pu_ldo15rf_aon + 1 + 1 + + + pu_mbg_aon + 0 + 0 + + + + + xtal_cfg + xtal_cfg. + 0x884 + + + xtal_rdy_sel_aon + 30 + 31 + + + xtal_gm_boost_aon + 28 + 29 + + + xtal_capcode_in_aon + 22 + 27 + + + xtal_capcode_out_aon + 16 + 21 + + + xtal_amp_ctrl_aon + 14 + 15 + + + xtal_sleep_aon + 13 + 13 + + + xtal_fast_startup_aon + 12 + 12 + + + xtal_buf_hp_aon + 8 + 11 + + + xtal_buf_en_aon + 4 + 7 + + + xtal_ext_sel_aon + 3 + 3 + + + xtal_capcode_extra_aon + 2 + 2 + + + xtal_bk_aon + 0 + 1 + + + + + tsen + tsen. + 0x888 + + + xtal_rdy_int_sel_aon + 30 + 31 + + + xtal_inn_cfg_en_aon + 29 + 29 + + + xtal_rdy + 28 + 28 + + + tsen_refcode_rfcal + 16 + 27 + + + tsen_refcode_corner + 0 + 11 + + + + + acomp0_ctrl + acomp0_ctrl. + 0x900 + + + acomp0_muxen + 26 + 26 + + + acomp0_pos_sel + 22 + 25 + + + acomp0_neg_sel + 18 + 21 + + + acomp0_level_sel + 12 + 17 + + + acomp0_bias_prog + 10 + 11 + + + acomp0_hyst_selp + 7 + 9 + + + acomp0_hyst_seln + 4 + 6 + + + acomp0_en + 0 + 0 + + + + + acomp1_ctrl + acomp1_ctrl. + 0x904 + + + acomp1_muxen + 26 + 26 + + + acomp1_pos_sel + 22 + 25 + + + acomp1_neg_sel + 18 + 21 + + + acomp1_level_sel + 12 + 17 + + + acomp1_bias_prog + 10 + 11 + + + acomp1_hyst_selp + 7 + 9 + + + acomp1_hyst_seln + 4 + 6 + + + acomp1_en + 0 + 0 + + + + + acomp_ctrl + acomp_ctrl. + 0x908 + + + acomp_reserved + 24 + 31 + + + acomp0_out_raw + 19 + 19 + + + acomp1_out_raw + 17 + 17 + + + acomp0_test_sel + 12 + 13 + + + acomp1_test_sel + 10 + 11 + + + acomp0_test_en + 9 + 9 + + + acomp1_test_en + 8 + 8 + + + acomp0_rstn_ana + 1 + 1 + + + acomp1_rstn_ana + 0 + 0 + + + + + gpadc_reg_cmd + gpadc_reg_cmd. + 0x90C + + + gpadc_sen_test_en + 30 + 30 + + + gpadc_sen_sel + 28 + 29 + + + gpadc_chip_sen_pu + 27 + 27 + + + gpadc_micboost_32db_en + 23 + 23 + + + gpadc_mic_pga2_gain + 21 + 22 + + + gpadc_mic1_diff + 20 + 20 + + + gpadc_mic2_diff + 19 + 19 + + + gpadc_dwa_en + 18 + 18 + + + gpadc_byp_micboost + 16 + 16 + + + gpadc_micpga_en + 15 + 15 + + + gpadc_micbias_en + 14 + 14 + + + gpadc_neg_gnd + 13 + 13 + + + gpadc_pos_sel + 8 + 12 + + + gpadc_neg_sel + 3 + 7 + + + gpadc_soft_rst + 2 + 2 + + + gpadc_conv_start + 1 + 1 + + + gpadc_global_en + 0 + 0 + + + + + gpadc_reg_config1 + gpadc_reg_config1. + 0x910 + + + gpadc_v18_sel + 29 + 30 + + + gpadc_v11_sel + 27 + 28 + + + gpadc_dither_en + 26 + 26 + + + gpadc_scan_en + 25 + 25 + + + gpadc_scan_length + 21 + 24 + + + gpadc_clk_div_ratio + 18 + 20 + + + gpadc_clk_ana_inv + 17 + 17 + + + gpadc_res_sel + 2 + 4 + + + gpadc_cont_conv_en + 1 + 1 + + + gpadc_cal_os_en + 0 + 0 + + + + + gpadc_reg_config2 + gpadc_reg_config2. + 0x914 + + + gpadc_tsvbe_low + 31 + 31 + + + gpadc_dly_sel + 28 + 30 + + + gpadc_pga1_gain + 25 + 27 + + + gpadc_pga2_gain + 22 + 24 + + + gpadc_test_sel + 19 + 21 + + + gpadc_test_en + 18 + 18 + + + gpadc_bias_sel + 17 + 17 + + + gpadc_chop_mode + 15 + 16 + + + gpadc_pga_vcmi_en + 14 + 14 + + + gpadc_pga_en + 13 + 13 + + + gpadc_pga_os_cal + 9 + 12 + + + gpadc_pga_vcm + 7 + 8 + + + gpadc_ts_en + 6 + 6 + + + gpadc_tsext_sel + 5 + 5 + + + gpadc_vbat_en + 4 + 4 + + + gpadc_vref_sel + 3 + 3 + + + gpadc_diff_mode + 2 + 2 + + + + + gpadc_reg_scn_pos1 + adc converation sequence 1 + 0x918 + + + gpadc_scan_pos_5 + 25 + 29 + + + gpadc_scan_pos_4 + 20 + 24 + + + gpadc_scan_pos_3 + 15 + 19 + + + gpadc_scan_pos_2 + 10 + 14 + + + gpadc_scan_pos_1 + 5 + 9 + + + gpadc_scan_pos_0 + 0 + 4 + + + + + gpadc_reg_scn_pos2 + adc converation sequence 2 + 0x91C + + + gpadc_scan_pos_11 + 25 + 29 + + + gpadc_scan_pos_10 + 20 + 24 + + + gpadc_scan_pos_9 + 15 + 19 + + + gpadc_scan_pos_8 + 10 + 14 + + + gpadc_scan_pos_7 + 5 + 9 + + + gpadc_scan_pos_6 + 0 + 4 + + + + + gpadc_reg_scn_neg1 + adc converation sequence 3 + 0x920 + + + gpadc_scan_neg_5 + 25 + 29 + + + gpadc_scan_neg_4 + 20 + 24 + + + gpadc_scan_neg_3 + 15 + 19 + + + gpadc_scan_neg_2 + 10 + 14 + + + gpadc_scan_neg_1 + 5 + 9 + + + gpadc_scan_neg_0 + 0 + 4 + + + + + gpadc_reg_scn_neg2 + adc converation sequence 4 + 0x924 + + + gpadc_scan_neg_11 + 25 + 29 + + + gpadc_scan_neg_10 + 20 + 24 + + + gpadc_scan_neg_9 + 15 + 19 + + + gpadc_scan_neg_8 + 10 + 14 + + + gpadc_scan_neg_7 + 5 + 9 + + + gpadc_scan_neg_6 + 0 + 4 + + + + + gpadc_reg_status + gpadc_reg_status. + 0x928 + + + gpadc_reserved + 16 + 31 + + + gpadc_data_rdy + 0 + 0 + + + + + gpadc_reg_isr + gpadc_reg_isr. + 0x92C + + + gpadc_pos_satur_mask + 9 + 9 + + + gpadc_neg_satur_mask + 8 + 8 + + + gpadc_pos_satur_clr + 5 + 5 + + + gpadc_neg_satur_clr + 4 + 4 + + + gpadc_pos_satur + 1 + 1 + + + gpadc_neg_satur + 0 + 0 + + + + + gpadc_reg_result + gpadc_reg_result. + 0x930 + + + gpadc_data_out + 0 + 25 + + + + + gpadc_reg_raw_result + gpadc_reg_raw_result. + 0x934 + + + gpadc_raw_data + 0 + 11 + + + + + gpadc_reg_define + gpadc_reg_define. + 0x938 + + + gpadc_os_cal_data + 0 + 15 + + + + + hbncore_resv0 + hbncore_resv0. + 0x93C + + + hbncore_resv0_data + 0 + 31 + + + + + hbncore_resv1 + hbncore_resv1. + 0x940 + + + hbncore_resv1_data + 0 + 31 + + + + + + + From 17a12b1d5f517e719996f02bd9172d3016ca8c5a Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sat, 24 Jul 2021 22:18:08 -0500 Subject: [PATCH 039/148] bug fix for field iterator --- script/svd2c.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/svd2c.py b/script/svd2c.py index 8eaa3d9..906c035 100755 --- a/script/svd2c.py +++ b/script/svd2c.py @@ -23,7 +23,7 @@ r_name = r.find('name').text r_offset = int(r.find('addressOffset').text, 16) Reg(r_name, r_offset + baseAddress) - for f in p.iter('field'): + for f in r.iter('field'): f_name = f.find('name').text lsb = int(f.find('lsb').text) msb = int(f.find('msb').text) From e3d7c8ff1417d257d47c23d4fa49810670cfc76e Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sat, 24 Jul 2021 22:24:09 -0500 Subject: [PATCH 040/148] add phy_hal --- src/bl602_wifi/phy_hal.c | 43 +++++ src/bl602_wifi/phy_hal.h | 3 +- src/include/soc/AON.h | 397 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 441 insertions(+), 2 deletions(-) create mode 100644 src/bl602_wifi/phy_hal.c create mode 100644 src/include/soc/AON.h diff --git a/src/bl602_wifi/phy_hal.c b/src/bl602_wifi/phy_hal.c new file mode 100644 index 0000000..2a7f6ca --- /dev/null +++ b/src/bl602_wifi/phy_hal.c @@ -0,0 +1,43 @@ +#include "phy_hal.h" +#include + +static struct phy_hal_tag hal_env; + +uint8_t hal_get_capcode(void) { + return AON->xtal_cfg.xtal_capcode_in_aon; +} + +void hal_set_capcode(uint32_t capcode) { + /* + AON->xtal_cfg.xtal_capcode_out_aon = capcode; + AON->xtal_cfg.xtal_capcode_in_aon = capcode; + */ + AON->xtal_cfg.value = (capcode & 0x3f) << 0x10 | (capcode & 0x3f) << 0x16 | AON->xtal_cfg.value & 0xf000ffff; +} + +void hal_set_capcode_asymm(uint32_t capcode_in, uint32_t capcode_out) { + /* + AON->xtal_cfg.xtal_capcode_out_aon = capcode_out; + AON->xtal_cfg.xtal_capcode_in_aon = capcode_in; + */ + + AON->xtal_cfg.value = (capcode_out & 0x3f) << 0x10 | (capcode_in & 0x3f) << 0x16 | AON->xtal_cfg.value & 0xf000ffff; +} + +void hal_get_capcode_asymm(uint8_t *capcode_in, uint8_t *capcode_out) { + if (capcode_in) { + *capcode_in = AON->xtal_cfg.xtal_capcode_in_aon; + } + if (capcode_out) { + *capcode_out = AON->xtal_cfg.xtal_capcode_out_aon; + } +} + +bool hal_get_temperature(int16_t *temperature) { + *temperature = hal_env.temperature; +} + +void hal_set_temperature(int16_t temperature) { + hal_env.temperature = temperature; +} + diff --git a/src/bl602_wifi/phy_hal.h b/src/bl602_wifi/phy_hal.h index 71902e5..eee906c 100644 --- a/src/bl602_wifi/phy_hal.h +++ b/src/bl602_wifi/phy_hal.h @@ -1,13 +1,12 @@ #ifndef _PHY_HAL_H_ #define _PHY_HAL_H_ #include + struct phy_hal_tag { int16_t temperature; // +0 uint8_t capcode; // +2 }; // :6:8 -//static struct phy_hal_tag hal_env; // :15:27 - uint8_t hal_get_capcode(void); // :43:9 void hal_set_capcode(uint32_t capcode); // :48:6 void hal_set_capcode_asymm(uint32_t capcode_in, uint32_t capcode_out); // :55:6 diff --git a/src/include/soc/AON.h b/src/include/soc/AON.h new file mode 100644 index 0000000..4089f3b --- /dev/null +++ b/src/include/soc/AON.h @@ -0,0 +1,397 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + uint8_t pad0[0x800]; + union { + uint32_t value; + struct { + uint32_t aon_resv : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pad0 : 4; + uint32_t pu_aon_dc_tbuf : 1; // @ 12 -- 12 # 0xffffefff + uint32_t pad1 : 7; + uint32_t ldo11_rt_pulldown : 1; // @ 20 -- 20 # 0xffefffff + uint32_t ldo11_rt_pulldown_sel : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t sw_pu_ldo11_rt : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t pad2 : 9; + }; + } aon; // @ 0x800 + union { + uint32_t value; + struct { + uint32_t tmux_aon : 3; // @ 2 -- 0 # 0xfffffff8 + uint32_t pad0 : 1; + uint32_t ten_aon : 1; // @ 4 -- 4 # 0xffffffef + uint32_t dten_xtal32k : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t ten_xtal32k : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t pad1 : 1; + uint32_t ten_vddcore_aon : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t ten_ldo11soc_aon : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t ten_dcdc18_0_aon : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t ten_dcdc18_1_aon : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t ten_bg_sys_aon : 1; // @ 12 -- 12 # 0xffffefff + uint32_t pad2 : 3; + uint32_t ten_ldo15rf_aon : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t ten_xtal_aon : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t dten_xtal_aon : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t ten_mbg_aon : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t ten_cip_misc_aon : 1; // @ 20 -- 20 # 0xffefffff + uint32_t pad3 : 11; + }; + } aon_common; // @ 0x804 + union { + uint32_t value; + struct { + uint32_t sw_soc_en_aon : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t sw_wb_en_aon : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t pad0 : 30; + }; + } aon_misc; // @ 0x808 + uint8_t pad1[0x4]; + union { + uint32_t value; + struct { + uint32_t pmip_resv : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pu_bg_sys_aon : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pad0 : 3; + uint32_t bg_sys_start_ctrl_aon : 1; // @ 12 -- 12 # 0xffffefff + uint32_t pad1 : 19; + }; + } bg_sys_top; // @ 0x810 + union { + uint32_t value; + struct { + uint32_t pad0 : 1; + uint32_t dcdc18_vout_sel_aon : 5; // @ 5 -- 1 # 0xffffffc1 + uint32_t pad1 : 2; + uint32_t dcdc18_vpfm_aon : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t dcdc18_osc_2m_mode_aon : 1; // @ 12 -- 12 # 0xffffefff + uint32_t pad2 : 3; + uint32_t dcdc18_osc_freq_trim_aon : 4; // @ 19 -- 16 # 0xfff0ffff + uint32_t dcdc18_slope_curr_sel_aon : 5; // @ 24 -- 20 # 0xfe0fffff + uint32_t dcdc18_stop_osc_aon : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t dcdc18_slow_osc_aon : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t dcdc18_osc_inhibit_t2_aon : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t dcdc18_sstart_time_aon : 2; // @ 29 -- 28 # 0xcfffffff + uint32_t pad3 : 1; + uint32_t dcdc18_rdy_aon : 1; // @ 31 -- 31 # 0x7fffffff + }; + } dcdc18_top_0; // @ 0x814 + union { + uint32_t value; + struct { + uint32_t dcdc18_force_cs_zvs_aon : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t dcdc18_cs_delay_aon : 3; // @ 3 -- 1 # 0xfffffff1 + uint32_t dcdc18_zvs_td_opt_aon : 3; // @ 6 -- 4 # 0xffffff8f + uint32_t pad0 : 1; + uint32_t dcdc18_nonoverlap_td_aon : 5; // @ 12 -- 8 # 0xffffe0ff + uint32_t pad1 : 3; + uint32_t dcdc18_rc_sel_aon : 4; // @ 19 -- 16 # 0xfff0ffff + uint32_t dcdc18_chf_sel_aon : 4; // @ 23 -- 20 # 0xff0fffff + uint32_t dcdc18_cfb_sel_aon : 4; // @ 27 -- 24 # 0xf0ffffff + uint32_t dcdc18_en_antiring_aon : 1; // @ 28 -- 28 # 0xefffffff + uint32_t dcdc18_pulldown_aon : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t pad2 : 2; + }; + } dcdc18_top_1; // @ 0x818 + union { + uint32_t value; + struct { + uint32_t pu_ldo11soc_aon : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 3; + uint32_t ldo11soc_sstart_sel_aon : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pad1 : 3; + uint32_t ldo11soc_sstart_delay_aon : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t ldo11soc_pulldown_aon : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t ldo11soc_pulldown_sel_aon : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t ldo11soc_vth_sel_aon : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t pad2 : 10; + uint32_t ldo11soc_cc_aon : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t pad3 : 2; + uint32_t ldo11soc_rdy_aon : 1; // @ 28 -- 28 # 0xefffffff + uint32_t ldo11soc_power_good_aon : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t pu_vddcore_misc_aon : 1; // @ 30 -- 30 # 0xbfffffff + uint32_t pmip_dc_tp_out_en_aon : 1; // @ 31 -- 31 # 0x7fffffff + }; + } ldo11soc_and_dctest; // @ 0x81c + union { + uint32_t value; + struct { + uint32_t pu_ir_psw_aon : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 31; + }; + } psw_irrcv; // @ 0x820 + uint8_t pad2[0x5c]; + union { + uint32_t value; + struct { + uint32_t pu_mbg_aon : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pu_ldo15rf_aon : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t pu_sfreg_aon : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 1; + uint32_t pu_xtal_buf_aon : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pu_xtal_aon : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad1 : 2; + uint32_t ldo15rf_sstart_sel_aon : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t ldo15rf_sstart_delay_aon : 2; // @ 10 -- 9 # 0xfffff9ff + uint32_t pad2 : 1; + uint32_t ldo15rf_pulldown_aon : 1; // @ 12 -- 12 # 0xffffefff + uint32_t ldo15rf_pulldown_sel_aon : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t pad3 : 2; + uint32_t ldo15rf_vout_sel_aon : 3; // @ 18 -- 16 # 0xfff8ffff + uint32_t pad4 : 5; + uint32_t ldo15rf_cc_aon : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t pad5 : 2; + uint32_t ldo15rf_bypass_aon : 1; // @ 28 -- 28 # 0xefffffff + uint32_t pad6 : 3; + }; + } rf_top_aon; // @ 0x880 + union { + uint32_t value; + struct { + uint32_t xtal_bk_aon : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t xtal_capcode_extra_aon : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t xtal_ext_sel_aon : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t xtal_buf_en_aon : 4; // @ 7 -- 4 # 0xffffff0f + uint32_t xtal_buf_hp_aon : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t xtal_fast_startup_aon : 1; // @ 12 -- 12 # 0xffffefff + uint32_t xtal_sleep_aon : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t xtal_amp_ctrl_aon : 2; // @ 15 -- 14 # 0xffff3fff + uint32_t xtal_capcode_out_aon : 6; // @ 21 -- 16 # 0xffc0ffff + uint32_t xtal_capcode_in_aon : 6; // @ 27 -- 22 # 0xf03fffff + uint32_t xtal_gm_boost_aon : 2; // @ 29 -- 28 # 0xcfffffff + uint32_t xtal_rdy_sel_aon : 2; // @ 31 -- 30 # 0x3fffffff + }; + } xtal_cfg; // @ 0x884 + union { + uint32_t value; + struct { + uint32_t tsen_refcode_corner : 12; // @ 11 -- 0 # 0xfffff000 + uint32_t pad0 : 4; + uint32_t tsen_refcode_rfcal : 12; // @ 27 -- 16 # 0xf000ffff + uint32_t xtal_rdy : 1; // @ 28 -- 28 # 0xefffffff + uint32_t xtal_inn_cfg_en_aon : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t xtal_rdy_int_sel_aon : 2; // @ 31 -- 30 # 0x3fffffff + }; + } tsen; // @ 0x888 + uint8_t pad3[0x74]; + union { + uint32_t value; + struct { + uint32_t acomp0_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 3; + uint32_t acomp0_hyst_seln : 3; // @ 6 -- 4 # 0xffffff8f + uint32_t acomp0_hyst_selp : 3; // @ 9 -- 7 # 0xfffffc7f + uint32_t acomp0_bias_prog : 2; // @ 11 -- 10 # 0xfffff3ff + uint32_t acomp0_level_sel : 6; // @ 17 -- 12 # 0xfffc0fff + uint32_t acomp0_neg_sel : 4; // @ 21 -- 18 # 0xffc3ffff + uint32_t acomp0_pos_sel : 4; // @ 25 -- 22 # 0xfc3fffff + uint32_t acomp0_muxen : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t pad1 : 5; + }; + } acomp0_ctrl; // @ 0x900 + union { + uint32_t value; + struct { + uint32_t acomp1_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 3; + uint32_t acomp1_hyst_seln : 3; // @ 6 -- 4 # 0xffffff8f + uint32_t acomp1_hyst_selp : 3; // @ 9 -- 7 # 0xfffffc7f + uint32_t acomp1_bias_prog : 2; // @ 11 -- 10 # 0xfffff3ff + uint32_t acomp1_level_sel : 6; // @ 17 -- 12 # 0xfffc0fff + uint32_t acomp1_neg_sel : 4; // @ 21 -- 18 # 0xffc3ffff + uint32_t acomp1_pos_sel : 4; // @ 25 -- 22 # 0xfc3fffff + uint32_t acomp1_muxen : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t pad1 : 5; + }; + } acomp1_ctrl; // @ 0x904 + union { + uint32_t value; + struct { + uint32_t acomp1_rstn_ana : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t acomp0_rstn_ana : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t pad0 : 6; + uint32_t acomp1_test_en : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t acomp0_test_en : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t acomp1_test_sel : 2; // @ 11 -- 10 # 0xfffff3ff + uint32_t acomp0_test_sel : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t pad1 : 3; + uint32_t acomp1_out_raw : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t pad2 : 1; + uint32_t acomp0_out_raw : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t pad3 : 4; + uint32_t acomp_reserved : 8; // @ 31 -- 24 # 0xffffff + }; + } acomp_ctrl; // @ 0x908 + union { + uint32_t value; + struct { + uint32_t gpadc_global_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t gpadc_conv_start : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t gpadc_soft_rst : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t gpadc_neg_sel : 5; // @ 7 -- 3 # 0xffffff07 + uint32_t gpadc_pos_sel : 5; // @ 12 -- 8 # 0xffffe0ff + uint32_t gpadc_neg_gnd : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t gpadc_micbias_en : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t gpadc_micpga_en : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t gpadc_byp_micboost : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad0 : 1; + uint32_t gpadc_dwa_en : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t gpadc_mic2_diff : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t gpadc_mic1_diff : 1; // @ 20 -- 20 # 0xffefffff + uint32_t gpadc_mic_pga2_gain : 2; // @ 22 -- 21 # 0xff9fffff + uint32_t gpadc_micboost_32db_en : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t pad1 : 3; + uint32_t gpadc_chip_sen_pu : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t gpadc_sen_sel : 2; // @ 29 -- 28 # 0xcfffffff + uint32_t gpadc_sen_test_en : 1; // @ 30 -- 30 # 0xbfffffff + uint32_t pad2 : 1; + }; + } gpadc_reg_cmd; // @ 0x90c + union { + uint32_t value; + struct { + uint32_t gpadc_cal_os_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t gpadc_cont_conv_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t gpadc_res_sel : 3; // @ 4 -- 2 # 0xffffffe3 + uint32_t pad0 : 12; + uint32_t gpadc_clk_ana_inv : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t gpadc_clk_div_ratio : 3; // @ 20 -- 18 # 0xffe3ffff + uint32_t gpadc_scan_length : 4; // @ 24 -- 21 # 0xfe1fffff + uint32_t gpadc_scan_en : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t gpadc_dither_en : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t gpadc_v11_sel : 2; // @ 28 -- 27 # 0xe7ffffff + uint32_t gpadc_v18_sel : 2; // @ 30 -- 29 # 0x9fffffff + uint32_t pad1 : 1; + }; + } gpadc_reg_config1; // @ 0x910 + union { + uint32_t value; + struct { + uint32_t pad0 : 2; + uint32_t gpadc_diff_mode : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t gpadc_vref_sel : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t gpadc_vbat_en : 1; // @ 4 -- 4 # 0xffffffef + uint32_t gpadc_tsext_sel : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t gpadc_ts_en : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t gpadc_pga_vcm : 2; // @ 8 -- 7 # 0xfffffe7f + uint32_t gpadc_pga_os_cal : 4; // @ 12 -- 9 # 0xffffe1ff + uint32_t gpadc_pga_en : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t gpadc_pga_vcmi_en : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t gpadc_chop_mode : 2; // @ 16 -- 15 # 0xfffe7fff + uint32_t gpadc_bias_sel : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t gpadc_test_en : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t gpadc_test_sel : 3; // @ 21 -- 19 # 0xffc7ffff + uint32_t gpadc_pga2_gain : 3; // @ 24 -- 22 # 0xfe3fffff + uint32_t gpadc_pga1_gain : 3; // @ 27 -- 25 # 0xf1ffffff + uint32_t gpadc_dly_sel : 3; // @ 30 -- 28 # 0x8fffffff + uint32_t gpadc_tsvbe_low : 1; // @ 31 -- 31 # 0x7fffffff + }; + } gpadc_reg_config2; // @ 0x914 + union { + uint32_t value; + struct { + uint32_t gpadc_scan_pos_0 : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t gpadc_scan_pos_1 : 5; // @ 9 -- 5 # 0xfffffc1f + uint32_t gpadc_scan_pos_2 : 5; // @ 14 -- 10 # 0xffff83ff + uint32_t gpadc_scan_pos_3 : 5; // @ 19 -- 15 # 0xfff07fff + uint32_t gpadc_scan_pos_4 : 5; // @ 24 -- 20 # 0xfe0fffff + uint32_t gpadc_scan_pos_5 : 5; // @ 29 -- 25 # 0xc1ffffff + uint32_t pad0 : 2; + }; + } gpadc_reg_scn_pos1; // @ 0x918 + union { + uint32_t value; + struct { + uint32_t gpadc_scan_pos_6 : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t gpadc_scan_pos_7 : 5; // @ 9 -- 5 # 0xfffffc1f + uint32_t gpadc_scan_pos_8 : 5; // @ 14 -- 10 # 0xffff83ff + uint32_t gpadc_scan_pos_9 : 5; // @ 19 -- 15 # 0xfff07fff + uint32_t gpadc_scan_pos_10 : 5; // @ 24 -- 20 # 0xfe0fffff + uint32_t gpadc_scan_pos_11 : 5; // @ 29 -- 25 # 0xc1ffffff + uint32_t pad0 : 2; + }; + } gpadc_reg_scn_pos2; // @ 0x91c + union { + uint32_t value; + struct { + uint32_t gpadc_scan_neg_0 : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t gpadc_scan_neg_1 : 5; // @ 9 -- 5 # 0xfffffc1f + uint32_t gpadc_scan_neg_2 : 5; // @ 14 -- 10 # 0xffff83ff + uint32_t gpadc_scan_neg_3 : 5; // @ 19 -- 15 # 0xfff07fff + uint32_t gpadc_scan_neg_4 : 5; // @ 24 -- 20 # 0xfe0fffff + uint32_t gpadc_scan_neg_5 : 5; // @ 29 -- 25 # 0xc1ffffff + uint32_t pad0 : 2; + }; + } gpadc_reg_scn_neg1; // @ 0x920 + union { + uint32_t value; + struct { + uint32_t gpadc_scan_neg_6 : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t gpadc_scan_neg_7 : 5; // @ 9 -- 5 # 0xfffffc1f + uint32_t gpadc_scan_neg_8 : 5; // @ 14 -- 10 # 0xffff83ff + uint32_t gpadc_scan_neg_9 : 5; // @ 19 -- 15 # 0xfff07fff + uint32_t gpadc_scan_neg_10 : 5; // @ 24 -- 20 # 0xfe0fffff + uint32_t gpadc_scan_neg_11 : 5; // @ 29 -- 25 # 0xc1ffffff + uint32_t pad0 : 2; + }; + } gpadc_reg_scn_neg2; // @ 0x924 + union { + uint32_t value; + struct { + uint32_t gpadc_data_rdy : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 15; + uint32_t gpadc_reserved : 16; // @ 31 -- 16 # 0xffff + }; + } gpadc_reg_status; // @ 0x928 + union { + uint32_t value; + struct { + uint32_t gpadc_neg_satur : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t gpadc_pos_satur : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t pad0 : 2; + uint32_t gpadc_neg_satur_clr : 1; // @ 4 -- 4 # 0xffffffef + uint32_t gpadc_pos_satur_clr : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad1 : 2; + uint32_t gpadc_neg_satur_mask : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t gpadc_pos_satur_mask : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t pad2 : 22; + }; + } gpadc_reg_isr; // @ 0x92c + union { + uint32_t value; + struct { + uint32_t gpadc_data_out : 26; // @ 25 -- 0 # 0xfc000000 + uint32_t pad0 : 6; + }; + } gpadc_reg_result; // @ 0x930 + union { + uint32_t value; + struct { + uint32_t gpadc_raw_data : 12; // @ 11 -- 0 # 0xfffff000 + uint32_t pad0 : 20; + }; + } gpadc_reg_raw_result; // @ 0x934 + union { + uint32_t value; + struct { + uint32_t gpadc_os_cal_data : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } gpadc_reg_define; // @ 0x938 + union { + uint32_t value; + struct { + uint32_t hbncore_resv0_data : 32; // @ 31 -- 0 # 0x0 + }; + } hbncore_resv0; // @ 0x93c + union { + uint32_t value; + struct { + uint32_t hbncore_resv1_data : 32; // @ 31 -- 0 # 0x0 + }; + } hbncore_resv1; // @ 0x940 + }; +} AON_regs; +#define AON_BASE 0x4000f000 +#define AON ((AON_regs* volatile)(AON_BASE)) \ No newline at end of file From da8f1d5786f69af2877ebb7c19b81915771b3919 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sat, 24 Jul 2021 23:21:59 -0500 Subject: [PATCH 041/148] add phy_helper --- src/bl602_wifi/phy_adapt.h | 3 + src/bl602_wifi/phy_helper.c | 134 +++ src/bl602_wifi/phy_helper.h | 39 + src/bl602_wifi/utils.h | 2 + src/include/soc/glb.h | 968 ++++++++++++++++++ src/include/soc/rf.h | 1921 +++++++++++++++++++++++++++++++++++ 6 files changed, 3067 insertions(+) create mode 100644 src/bl602_wifi/phy_helper.c create mode 100644 src/bl602_wifi/phy_helper.h create mode 100644 src/include/soc/glb.h create mode 100644 src/include/soc/rf.h diff --git a/src/bl602_wifi/phy_adapt.h b/src/bl602_wifi/phy_adapt.h index 7fbe645..33e074e 100644 --- a/src/bl602_wifi/phy_adapt.h +++ b/src/bl602_wifi/phy_adapt.h @@ -91,4 +91,7 @@ void pa_input(uint8_t id, struct rx_hd *rhd); int8_t pa_alloc(uint32_t vif_addr); void pa_reset(uint8_t id); void pa_free(uint8_t id); + +float calc_ppm_dsss(uint8_t rxv_freqoff); +float calc_ppm_ofdm(uint16_t rxv_freqoff); #endif \ No newline at end of file diff --git a/src/bl602_wifi/phy_helper.c b/src/bl602_wifi/phy_helper.c new file mode 100644 index 0000000..45a5c1f --- /dev/null +++ b/src/bl602_wifi/phy_helper.c @@ -0,0 +1,134 @@ +#include "phy_helper.h" +#include +#include +#include +#include + +#include "utils.h" + +static char *rc_state_str[8] = { + "RC_IDLE", + "RC_RX2ON", + "RC_TX2ON", + "RC_RXON", + "RC_TX2PAON", + "UNKNOWN", + "UNKNOWN", + "RC_TXPAON", +}; + +static char *rf_state_str[8] = { + "RF_PD", + "RF_SB", + "RF_LO", + "RF_RX", + "RF_TX", + "RF_T2RI", + "RF_R2T", + "RF_MS", +}; + +static struct dump_data_t dump_data_poll[18]; // :86:27 +static uint8_t dump_data_ptr; // :87:16 + +int bl60x_check_mac_status(int * is_ok) { + int ok = 0; + for (int i = 0; i < dump_data_ptr; i++) { + if (dump_data_poll[i].mac_debugRegHWSM2 != 0x8801e000) { + ok = 1; + break; + } + } + * is_ok = ok; +} + +void helper_channel_monitor(uint32_t chanfreq, timer_func_ptr * timer_func, int nrepeats, int mon_time_ms) { + // no code + return ; +} + +void helper_record_all_states(char * func_name) { + int id = dump_data_ptr; + dump_data_poll[id].func_name = func_name; + dump_data_poll[id].time = MAC_CORE->MONOTONIC_COUNTER_2_LO.value; + + helper_record_rc_rf_states(&dump_data_poll[id].rc_state, &dump_data_poll[id].rf_state); + + dump_data_poll[id].mac_debugRegHWSM1 = MAC_CORE->DEBUG_HWSM_1.value; + dump_data_poll[id].mac_debugRegHWSM2 = MAC_CORE->DEBUG_HWSM_2.value; + + MAC_CORE->DEBUG_PORT_SEL.debugPortSel1 = 0x31; + MAC_CORE->DEBUG_PORT_SEL.debugPortSel2 = 0; + + *(uint32_t*)(&dump_data_poll[id].mac_debugPortCoex) = MAC_CORE->DEBUG_PORT_VALUE.value; + + MAC_CORE->DEBUG_PORT_SEL.debugPortSel1 = 0xb; + MAC_CORE->DEBUG_PORT_SEL.debugPortSel2 = 0x2f; + + *(uint32_t*)(&dump_data_poll[id].mac_debugPortMacPhyIf) = MAC_CORE->DEBUG_PORT_VALUE.value; + + SYSCTRL->r074 = 0x33a; + SYSCTRL->diag_conf.diag_sel = 0x14; + + GLB->DBG_SEL_LL.value = 0x4; + GLB->DBG_SEL_LH.value = 0x40000004; + GLB->DBG_SEL_HL.value = 0x80000004; + GLB->DBG_SEL_HH.value = 0xc0000004; + + GLB->debug.debug_oe = 0; + + uint32_t debug = GLB->debug.value; + + dump_data_poll[id].phy_debugPortTDTX = (uint16_t)(debug >> 1); + dump_data_poll[id].phy_debugPortMainFSM = (uint16_t)(debug >> 0x11); + + SYSCTRL->r074 = 0xb09; + + GLB->debug.debug_oe = 0; + debug = GLB->debug.value; + dump_data_poll[id].phy_debugPortDSSSCCK1 = (uint16_t)(debug >> 1); + dump_data_poll[id].phy_debugPortDSSSCCKTx = (uint16_t)(debug >> 0x11); + dump_data_ptr = (dump_data_ptr + 1) & 0xf; +} + +void helper_record_dump(void) { + puts("========= helper_record_dump\r\n"); + for (int i = 0; i < dump_data_ptr; i++) { + struct dump_data_t *data = &dump_data_poll[i]; + printf("[%d] time %ld, func %s\r\n", i, data->time, data->func_name); + printf("MAC: %08lx: rxControlCs %d,txControlCs %d,macControlCs %d\r\n", + data->mac_debugRegHWSM2, + data->mac_debugRegHWSM2 & 0x3f, + data->mac_debugRegHWSM2 >> 8 & 0x1ff, + data->mac_debugRegHWSM2 >> 24 & 0xff + ); + printf("MAC: Coex %04x,Backoff %04x,MPIF %04x,MPIF2 %04x\r\n", + (uint32_t)data->mac_debugPortCoex, + (uint32_t)data->mac_debugPortBackoff, + (uint32_t)data->mac_debugPortMacPhyIf, + (uint32_t)data->mac_debugPortMacPhyIf2 + ); + printf("PHY: MainFSM %04x,TDTX %04x,DSSSCCK1 %04x,DSSSCCKTx %04x\r\n", + (uint32_t)data->phy_debugPortMainFSM, + (uint32_t)data->phy_debugPortTDTX, + (uint32_t)data->phy_debugPortDSSSCCK1, + (uint32_t)data->phy_debugPortDSSSCCKTx + ); + + printf("RFC: RC %s, RF %s\r\n", rc_state_str[data->rc_state], rf_state_str[data->rf_state]); + } + printf("\r\n\r\n"); +} + +void helper_record_rc_rf_states(uint32_t * rc_state, uint32_t * rf_state) { + RF->rfif_dfe_ctrl0.value = RF->rfif_dfe_ctrl0.value & 0xfffffff | 0x10000000; + uint32_t x = RF->rfif_test_read.value; + RF->rfif_dfe_ctrl0.value = RF->rfif_dfe_ctrl0.value & 0xfffffff | 0x20000000; + x = RF->rfif_test_read.value; + *rc_state = x >> 0x1c & 7; + *rf_state = x >> 0x19 & 7; +} + +void helper_record_reset(void) { + dump_data_ptr = 0; +} diff --git a/src/bl602_wifi/phy_helper.h b/src/bl602_wifi/phy_helper.h new file mode 100644 index 0000000..81c9cb2 --- /dev/null +++ b/src/bl602_wifi/phy_helper.h @@ -0,0 +1,39 @@ +#ifndef _PHY_HELPER_H_ +#define _PHY_HELPER_H_ +#include + +typedef long long (*timer_func_ptr)(void*); // :237:21 + +struct HWStateMachineReg { + uint32_t rxControl:6; // +0 + uint32_t reserved_7_6:2; // +0 + uint32_t txControl:9; // +0 + uint32_t reserved_23_17:7; // +0 + uint32_t macControl:8; // +0 +}; // :59:8 + +struct dump_data_t { + uint32_t time; // +0 + const char *func_name; // +4 + uint32_t rc_state; // +8 + uint32_t rf_state; // +12 + uint32_t mac_debugRegHWSM1; // +16 + uint32_t mac_debugRegHWSM2; // +20 + uint16_t mac_debugPortCoex; // +24 + uint16_t mac_debugPortBackoff; // +26 + uint16_t mac_debugPortMacPhyIf; // +28 + uint16_t mac_debugPortMacPhyIf2; // +30 + uint16_t phy_debugPortMainFSM; // +32 + uint16_t phy_debugPortTDTX; // +34 + uint16_t phy_debugPortDSSSCCK1; // +36 + uint16_t phy_debugPortDSSSCCKTx; // +38 +}; // :68:8 + +int bl60x_check_mac_status(int * is_ok); +void helper_channel_monitor(uint32_t chanfreq, timer_func_ptr * timer_func, int nrepeats, int mon_time_ms); +void helper_record_all_states(char * func_name); +void helper_record_dump(void); +void helper_record_rc_rf_states(uint32_t * rc_state, uint32_t * rf_state); +void helper_record_reset(void); + +#endif \ No newline at end of file diff --git a/src/bl602_wifi/utils.h b/src/bl602_wifi/utils.h index fe930e2..68cdca3 100644 --- a/src/bl602_wifi/utils.h +++ b/src/bl602_wifi/utils.h @@ -1,3 +1,5 @@ #ifndef __UTILS_H_ #define ABS(x) (((x) > 0) ? (x) : (-(x))) +int puts(char *s); +int printf(char *fmt,...); #endif \ No newline at end of file diff --git a/src/include/soc/glb.h b/src/include/soc/glb.h new file mode 100644 index 0000000..6fb5e34 --- /dev/null +++ b/src/include/soc/glb.h @@ -0,0 +1,968 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + union { + uint32_t value; + struct { + uint32_t reg_pll_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t reg_fclk_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t reg_hclk_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t reg_bclk_en : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t reg_pll_sel : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t hbn_root_clk_sel : 2; // @ 7 -- 6 # 0xffffff3f + uint32_t reg_hclk_div : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t reg_bclk_div : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t fclk_sw_state : 3; // @ 26 -- 24 # 0xf8ffffff + uint32_t chip_rdy : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t glb_id : 4; // @ 31 -- 28 # 0xfffffff + }; + } clk_cfg0; // @ 0x0 + union { + uint32_t value; + struct { + uint32_t wifi_mac_core_div : 4; // @ 3 -- 0 # 0xfffffff0 + uint32_t wifi_mac_wt_div : 4; // @ 7 -- 4 # 0xffffff0f + uint32_t pad0 : 8; + uint32_t ble_clk_sel : 6; // @ 21 -- 16 # 0xffc0ffff + uint32_t pad1 : 2; + uint32_t ble_en : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t pad2 : 7; + }; + } clk_cfg1; // @ 0x4 + union { + uint32_t value; + struct { + uint32_t uart_clk_div : 3; // @ 2 -- 0 # 0xfffffff8 + uint32_t pad0 : 1; + uint32_t uart_clk_en : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pad1 : 2; + uint32_t hbn_uart_clk_sel : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t sf_clk_div : 3; // @ 10 -- 8 # 0xfffff8ff + uint32_t sf_clk_en : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t sf_clk_sel : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t sf_clk_sel2 : 2; // @ 15 -- 14 # 0xffff3fff + uint32_t ir_clk_div : 6; // @ 21 -- 16 # 0xffc0ffff + uint32_t pad2 : 1; + uint32_t ir_clk_en : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t dma_clk_en : 8; // @ 31 -- 24 # 0xffffff + }; + } clk_cfg2; // @ 0x8 + union { + uint32_t value; + struct { + uint32_t spi_clk_div : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t pad0 : 3; + uint32_t spi_clk_en : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pad1 : 7; + uint32_t i2c_clk_div : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t i2c_clk_en : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t pad2 : 7; + }; + } clk_cfg3; // @ 0xc + union { + uint32_t value; + struct { + uint32_t swrst_s00 : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t swrst_s01 : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t pad0 : 2; + uint32_t swrst_s20 : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pad1 : 3; + uint32_t swrst_s30 : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pad2 : 23; + }; + } swrst_cfg0; // @ 0x10 + union { + uint32_t value; + struct { + uint32_t swrst_s10 : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t swrst_s11 : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t swrst_s12 : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t swrst_s13 : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t swrst_s14 : 1; // @ 4 -- 4 # 0xffffffef + uint32_t swrst_s15 : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t swrst_s16 : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t swrst_s17 : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t swrst_s18 : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t swrst_s19 : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t swrst_s1a : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t swrst_s1b : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t swrst_s1c : 1; // @ 12 -- 12 # 0xffffefff + uint32_t swrst_s1d : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t swrst_s1e : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t swrst_s1f : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t swrst_s1a0 : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t swrst_s1a1 : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t swrst_s1a2 : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t swrst_s1a3 : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t swrst_s1a4 : 1; // @ 20 -- 20 # 0xffefffff + uint32_t swrst_s1a5 : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t swrst_s1a6 : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t swrst_s1a7 : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t pad0 : 8; + }; + } swrst_cfg1; // @ 0x14 + union { + uint32_t value; + struct { + uint32_t reg_ctrl_pwron_rst : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t reg_ctrl_cpu_reset : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t reg_ctrl_sys_reset : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 1; + uint32_t reg_ctrl_reset_dummy : 4; // @ 7 -- 4 # 0xffffff0f + uint32_t pad1 : 16; + uint32_t pka_clk_sel : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t pad2 : 7; + }; + } swrst_cfg2; // @ 0x18 + uint32_t swrst_cfg3; // @ 0x1c + union { + uint32_t value; + struct { + uint32_t cgen_m : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pad0 : 24; + }; + } cgen_cfg0; // @ 0x20 + union { + uint32_t value; + struct { + uint32_t cgen_s1 : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t cgen_s1a : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t pad0 : 8; + }; + } cgen_cfg1; // @ 0x24 + union { + uint32_t value; + struct { + uint32_t cgen_s2 : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 3; + uint32_t cgen_s3 : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pad1 : 27; + }; + } cgen_cfg2; // @ 0x28 + uint32_t cgen_cfg3; // @ 0x2c + union { + uint32_t value; + struct { + uint32_t irom_mbist_mode : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t hsram_mbist_mode : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t tag_mbist_mode : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t ocram_mbist_mode : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t wifi_mbist_mode : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pad0 : 26; + uint32_t reg_mbist_rst_n : 1; // @ 31 -- 31 # 0x7fffffff + }; + } MBIST_CTL; // @ 0x30 + union { + uint32_t value; + struct { + uint32_t irom_mbist_done : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t hsram_mbist_done : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t tag_mbist_done : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t ocram_mbist_done : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t wifi_mbist_done : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pad0 : 11; + uint32_t irom_mbist_fail : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t hsram_mbist_fail : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t tag_mbist_fail : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t ocram_mbist_fail : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t wifi_mbist_fail : 1; // @ 20 -- 20 # 0xffefffff + uint32_t pad1 : 11; + }; + } MBIST_STAT; // @ 0x34 + uint8_t pad0[0x18]; + union { + uint32_t value; + struct { + uint32_t bmx_timeout_en : 4; // @ 3 -- 0 # 0xfffffff0 + uint32_t bmx_arb_mode : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t pad0 : 2; + uint32_t bmx_err_en : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t bmx_busy_option_dis : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t bmx_gating_dis : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t pad1 : 1; + uint32_t hsel_option : 4; // @ 15 -- 12 # 0xffff0fff + uint32_t pds_apb_cfg : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t hbn_apb_cfg : 8; // @ 31 -- 24 # 0xffffff + }; + } bmx_cfg1; // @ 0x50 + union { + uint32_t value; + struct { + uint32_t bmx_err_addr_dis : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 3; + uint32_t bmx_err_dec : 1; // @ 4 -- 4 # 0xffffffef + uint32_t bmx_err_tz : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad1 : 22; + uint32_t bmx_dbg_sel : 4; // @ 31 -- 28 # 0xfffffff + }; + } bmx_cfg2; // @ 0x54 + union { + uint32_t value; + struct { + uint32_t bmx_err_addr : 32; // @ 31 -- 0 # 0x0 + }; + } bmx_err_addr; // @ 0x58 + union { + uint32_t value; + struct { + uint32_t bmx_dbg_out : 32; // @ 31 -- 0 # 0x0 + }; + } bmx_dbg_out; // @ 0x5c + union { + uint32_t value; + struct { + uint32_t rsvd_31_0 : 32; // @ 31 -- 0 # 0x0 + }; + } rsv0; // @ 0x60 + union { + uint32_t value; + struct { + uint32_t rsvd_31_0 : 32; // @ 31 -- 0 # 0x0 + }; + } rsv1; // @ 0x64 + union { + uint32_t value; + struct { + uint32_t rsvd_31_0 : 32; // @ 31 -- 0 # 0x0 + }; + } rsv2; // @ 0x68 + union { + uint32_t value; + struct { + uint32_t rsvd_31_0 : 32; // @ 31 -- 0 # 0x0 + }; + } rsv3; // @ 0x6c + union { + uint32_t value; + struct { + uint32_t reg_sram_ret : 32; // @ 31 -- 0 # 0x0 + }; + } sram_ret; // @ 0x70 + union { + uint32_t value; + struct { + uint32_t reg_sram_slp : 32; // @ 31 -- 0 # 0x0 + }; + } sram_slp; // @ 0x74 + union { + uint32_t value; + struct { + uint32_t reg_sram_parm : 32; // @ 31 -- 0 # 0x0 + }; + } sram_parm; // @ 0x78 + union { + uint32_t value; + struct { + uint32_t em_sel : 4; // @ 3 -- 0 # 0xfffffff0 + uint32_t pad0 : 28; + }; + } seam_misc; // @ 0x7c + union { + uint32_t value; + struct { + uint32_t reg_bd_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t reg_ext_rst_smt : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t jtag_swap_set : 6; // @ 7 -- 2 # 0xffffff03 + uint32_t swap_sflash_io_3_io_0 : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t sel_embedded_sflash : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t pad0 : 2; + uint32_t reg_spi_0_master_mode : 1; // @ 12 -- 12 # 0xffffefff + uint32_t reg_spi_0_swap : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t pad1 : 1; + uint32_t reg_cci_use_jtag_pin : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t reg_cci_use_sdio_pin : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t p1_adc_test_with_cci : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t p2_dac_test_with_cci : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t p3_cci_use_io_2_5 : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t p4_adc_test_with_jtag : 1; // @ 20 -- 20 # 0xffefffff + uint32_t p5_dac_test_with_jtag : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t p6_sdio_use_io_0_5 : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t p7_jtag_use_io_2_5 : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t uart_swap_set : 3; // @ 26 -- 24 # 0xf8ffffff + uint32_t pad2 : 5; + }; + } glb_parm; // @ 0x80 + uint8_t pad1[0xc]; + union { + uint32_t value; + struct { + uint32_t cpu_rtc_div : 17; // @ 16 -- 0 # 0xfffe0000 + uint32_t pad0 : 1; + uint32_t cpu_rtc_en : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t cpu_rtc_sel : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t debug_ndreset_gate : 1; // @ 20 -- 20 # 0xffefffff + uint32_t pad1 : 11; + }; + } CPU_CLK_CFG; // @ 0x90 + uint8_t pad2[0x10]; + union { + uint32_t value; + struct { + uint32_t gpadc_32m_clk_div : 6; // @ 5 -- 0 # 0xffffffc0 + uint32_t pad0 : 1; + uint32_t gpadc_32m_clk_sel : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t gpadc_32m_div_en : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pad1 : 23; + }; + } GPADC_32M_SRC_CTRL; // @ 0xa4 + union { + uint32_t value; + struct { + uint32_t dig_32k_div : 11; // @ 10 -- 0 # 0xfffff800 + uint32_t pad0 : 1; + uint32_t dig_32k_en : 1; // @ 12 -- 12 # 0xffffefff + uint32_t dig_32k_comp : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t pad1 : 2; + uint32_t dig_512k_div : 7; // @ 22 -- 16 # 0xff80ffff + uint32_t pad2 : 1; + uint32_t dig_512k_en : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t dig_512k_comp : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t pad3 : 2; + uint32_t dig_clk_src_sel : 1; // @ 28 -- 28 # 0xefffffff + uint32_t pad4 : 2; + uint32_t reg_en_platform_wakeup : 1; // @ 31 -- 31 # 0x7fffffff + }; + } DIG32K_WAKEUP_CTRL; // @ 0xa8 + union { + uint32_t value; + struct { + uint32_t coex_bt_channel : 7; // @ 6 -- 0 # 0xffffff80 + uint32_t coex_bt_pti : 4; // @ 10 -- 7 # 0xfffff87f + uint32_t coex_bt_bw : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t en_gpio_bt_coex : 1; // @ 12 -- 12 # 0xffffefff + uint32_t pad0 : 19; + }; + } WIFI_BT_COEX_CTRL; // @ 0xac + uint8_t pad3[0x10]; + union { + uint32_t value; + struct { + uint32_t uart_sig_0_sel : 4; // @ 3 -- 0 # 0xfffffff0 + uint32_t uart_sig_1_sel : 4; // @ 7 -- 4 # 0xffffff0f + uint32_t uart_sig_2_sel : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t uart_sig_3_sel : 4; // @ 15 -- 12 # 0xffff0fff + uint32_t uart_sig_4_sel : 4; // @ 19 -- 16 # 0xfff0ffff + uint32_t uart_sig_5_sel : 4; // @ 23 -- 20 # 0xff0fffff + uint32_t uart_sig_6_sel : 4; // @ 27 -- 24 # 0xf0ffffff + uint32_t uart_sig_7_sel : 4; // @ 31 -- 28 # 0xfffffff + }; + } UART_SIG_SEL_0; // @ 0xc0 + uint8_t pad4[0xc]; + union { + uint32_t value; + struct { + uint32_t reg_dbg_ll_ctrl : 32; // @ 31 -- 0 # 0x0 + }; + } DBG_SEL_LL; // @ 0xd0 + union { + uint32_t value; + struct { + uint32_t reg_dbg_lh_ctrl : 32; // @ 31 -- 0 # 0x0 + }; + } DBG_SEL_LH; // @ 0xd4 + union { + uint32_t value; + struct { + uint32_t reg_dbg_hl_ctrl : 32; // @ 31 -- 0 # 0x0 + }; + } DBG_SEL_HL; // @ 0xd8 + union { + uint32_t value; + struct { + uint32_t reg_dbg_hh_ctrl : 32; // @ 31 -- 0 # 0x0 + }; + } DBG_SEL_HH; // @ 0xdc + union { + uint32_t value; + struct { + uint32_t debug_oe : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t debug_i : 31; // @ 31 -- 1 # 0x1 + }; + } debug; // @ 0xe0 + uint8_t pad5[0x1c]; + union { + uint32_t value; + struct { + uint32_t reg_gpio_0_ie : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t reg_gpio_0_smt : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t reg_gpio_0_drv : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t reg_gpio_0_pu : 1; // @ 4 -- 4 # 0xffffffef + uint32_t reg_gpio_0_pd : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad0 : 2; + uint32_t reg_gpio_0_func_sel : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t real_gpio_0_func_sel : 4; // @ 15 -- 12 # 0xffff0fff + uint32_t reg_gpio_1_ie : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t reg_gpio_1_smt : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t reg_gpio_1_drv : 2; // @ 19 -- 18 # 0xfff3ffff + uint32_t reg_gpio_1_pu : 1; // @ 20 -- 20 # 0xffefffff + uint32_t reg_gpio_1_pd : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t pad1 : 2; + uint32_t reg_gpio_1_func_sel : 4; // @ 27 -- 24 # 0xf0ffffff + uint32_t real_gpio_1_func_sel : 4; // @ 31 -- 28 # 0xfffffff + }; + } GPIO_CFGCTL0; // @ 0x100 + union { + uint32_t value; + struct { + uint32_t reg_gpio_2_ie : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t reg_gpio_2_smt : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t reg_gpio_2_drv : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t reg_gpio_2_pu : 1; // @ 4 -- 4 # 0xffffffef + uint32_t reg_gpio_2_pd : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad0 : 2; + uint32_t reg_gpio_2_func_sel : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t real_gpio_2_func_sel : 4; // @ 15 -- 12 # 0xffff0fff + uint32_t reg_gpio_3_ie : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t reg_gpio_3_smt : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t reg_gpio_3_drv : 2; // @ 19 -- 18 # 0xfff3ffff + uint32_t reg_gpio_3_pu : 1; // @ 20 -- 20 # 0xffefffff + uint32_t reg_gpio_3_pd : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t pad1 : 2; + uint32_t reg_gpio_3_func_sel : 4; // @ 27 -- 24 # 0xf0ffffff + uint32_t real_gpio_3_func_sel : 4; // @ 31 -- 28 # 0xfffffff + }; + } GPIO_CFGCTL1; // @ 0x104 + union { + uint32_t value; + struct { + uint32_t reg_gpio_4_ie : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t reg_gpio_4_smt : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t reg_gpio_4_drv : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t reg_gpio_4_pu : 1; // @ 4 -- 4 # 0xffffffef + uint32_t reg_gpio_4_pd : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad0 : 2; + uint32_t reg_gpio_4_func_sel : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t real_gpio_4_func_sel : 4; // @ 15 -- 12 # 0xffff0fff + uint32_t reg_gpio_5_ie : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t reg_gpio_5_smt : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t reg_gpio_5_drv : 2; // @ 19 -- 18 # 0xfff3ffff + uint32_t reg_gpio_5_pu : 1; // @ 20 -- 20 # 0xffefffff + uint32_t reg_gpio_5_pd : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t pad1 : 2; + uint32_t reg_gpio_5_func_sel : 4; // @ 27 -- 24 # 0xf0ffffff + uint32_t real_gpio_5_func_sel : 4; // @ 31 -- 28 # 0xfffffff + }; + } GPIO_CFGCTL2; // @ 0x108 + union { + uint32_t value; + struct { + uint32_t reg_gpio_6_ie : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t reg_gpio_6_smt : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t reg_gpio_6_drv : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t reg_gpio_6_pu : 1; // @ 4 -- 4 # 0xffffffef + uint32_t reg_gpio_6_pd : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad0 : 2; + uint32_t reg_gpio_6_func_sel : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t pad1 : 4; + uint32_t reg_gpio_7_ie : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t reg_gpio_7_smt : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t reg_gpio_7_drv : 2; // @ 19 -- 18 # 0xfff3ffff + uint32_t reg_gpio_7_pu : 1; // @ 20 -- 20 # 0xffefffff + uint32_t reg_gpio_7_pd : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t pad2 : 2; + uint32_t reg_gpio_7_func_sel : 4; // @ 27 -- 24 # 0xf0ffffff + uint32_t pad3 : 4; + }; + } GPIO_CFGCTL3; // @ 0x10c + union { + uint32_t value; + struct { + uint32_t reg_gpio_8_ie : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t reg_gpio_8_smt : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t reg_gpio_8_drv : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t reg_gpio_8_pu : 1; // @ 4 -- 4 # 0xffffffef + uint32_t reg_gpio_8_pd : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad0 : 2; + uint32_t reg_gpio_8_func_sel : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t pad1 : 4; + uint32_t reg_gpio_9_ie : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t reg_gpio_9_smt : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t reg_gpio_9_drv : 2; // @ 19 -- 18 # 0xfff3ffff + uint32_t reg_gpio_9_pu : 1; // @ 20 -- 20 # 0xffefffff + uint32_t reg_gpio_9_pd : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t pad2 : 2; + uint32_t reg_gpio_9_func_sel : 4; // @ 27 -- 24 # 0xf0ffffff + uint32_t pad3 : 4; + }; + } GPIO_CFGCTL4; // @ 0x110 + union { + uint32_t value; + struct { + uint32_t reg_gpio_10_ie : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t reg_gpio_10_smt : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t reg_gpio_10_drv : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t reg_gpio_10_pu : 1; // @ 4 -- 4 # 0xffffffef + uint32_t reg_gpio_10_pd : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad0 : 2; + uint32_t reg_gpio_10_func_sel : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t pad1 : 4; + uint32_t reg_gpio_11_ie : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t reg_gpio_11_smt : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t reg_gpio_11_drv : 2; // @ 19 -- 18 # 0xfff3ffff + uint32_t reg_gpio_11_pu : 1; // @ 20 -- 20 # 0xffefffff + uint32_t reg_gpio_11_pd : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t pad2 : 2; + uint32_t reg_gpio_11_func_sel : 4; // @ 27 -- 24 # 0xf0ffffff + uint32_t pad3 : 4; + }; + } GPIO_CFGCTL5; // @ 0x114 + union { + uint32_t value; + struct { + uint32_t reg_gpio_12_ie : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t reg_gpio_12_smt : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t reg_gpio_12_drv : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t reg_gpio_12_pu : 1; // @ 4 -- 4 # 0xffffffef + uint32_t reg_gpio_12_pd : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad0 : 2; + uint32_t reg_gpio_12_func_sel : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t pad1 : 4; + uint32_t reg_gpio_13_ie : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t reg_gpio_13_smt : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t reg_gpio_13_drv : 2; // @ 19 -- 18 # 0xfff3ffff + uint32_t reg_gpio_13_pu : 1; // @ 20 -- 20 # 0xffefffff + uint32_t reg_gpio_13_pd : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t pad2 : 2; + uint32_t reg_gpio_13_func_sel : 4; // @ 27 -- 24 # 0xf0ffffff + uint32_t pad3 : 4; + }; + } GPIO_CFGCTL6; // @ 0x118 + union { + uint32_t value; + struct { + uint32_t reg_gpio_14_ie : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t reg_gpio_14_smt : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t reg_gpio_14_drv : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t reg_gpio_14_pu : 1; // @ 4 -- 4 # 0xffffffef + uint32_t reg_gpio_14_pd : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad0 : 2; + uint32_t reg_gpio_14_func_sel : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t pad1 : 4; + uint32_t reg_gpio_15_ie : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t reg_gpio_15_smt : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t reg_gpio_15_drv : 2; // @ 19 -- 18 # 0xfff3ffff + uint32_t reg_gpio_15_pu : 1; // @ 20 -- 20 # 0xffefffff + uint32_t reg_gpio_15_pd : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t pad2 : 2; + uint32_t reg_gpio_15_func_sel : 4; // @ 27 -- 24 # 0xf0ffffff + uint32_t pad3 : 4; + }; + } GPIO_CFGCTL7; // @ 0x11c + union { + uint32_t value; + struct { + uint32_t reg_gpio_16_ie : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t reg_gpio_16_smt : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t reg_gpio_16_drv : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t reg_gpio_16_pu : 1; // @ 4 -- 4 # 0xffffffef + uint32_t reg_gpio_16_pd : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad0 : 2; + uint32_t reg_gpio_16_func_sel : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t pad1 : 4; + uint32_t reg_gpio_17_ie : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t reg_gpio_17_smt : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t reg_gpio_17_drv : 2; // @ 19 -- 18 # 0xfff3ffff + uint32_t reg_gpio_17_pu : 1; // @ 20 -- 20 # 0xffefffff + uint32_t reg_gpio_17_pd : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t pad2 : 2; + uint32_t reg_gpio_17_func_sel : 4; // @ 27 -- 24 # 0xf0ffffff + uint32_t pad3 : 4; + }; + } GPIO_CFGCTL8; // @ 0x120 + union { + uint32_t value; + struct { + uint32_t reg_gpio_18_ie : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t reg_gpio_18_smt : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t reg_gpio_18_drv : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t reg_gpio_18_pu : 1; // @ 4 -- 4 # 0xffffffef + uint32_t reg_gpio_18_pd : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad0 : 2; + uint32_t reg_gpio_18_func_sel : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t pad1 : 4; + uint32_t reg_gpio_19_ie : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t reg_gpio_19_smt : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t reg_gpio_19_drv : 2; // @ 19 -- 18 # 0xfff3ffff + uint32_t reg_gpio_19_pu : 1; // @ 20 -- 20 # 0xffefffff + uint32_t reg_gpio_19_pd : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t pad2 : 2; + uint32_t reg_gpio_19_func_sel : 4; // @ 27 -- 24 # 0xf0ffffff + uint32_t pad3 : 4; + }; + } GPIO_CFGCTL9; // @ 0x124 + union { + uint32_t value; + struct { + uint32_t reg_gpio_20_ie : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t reg_gpio_20_smt : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t reg_gpio_20_drv : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t reg_gpio_20_pu : 1; // @ 4 -- 4 # 0xffffffef + uint32_t reg_gpio_20_pd : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad0 : 2; + uint32_t reg_gpio_20_func_sel : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t pad1 : 4; + uint32_t reg_gpio_21_ie : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t reg_gpio_21_smt : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t reg_gpio_21_drv : 2; // @ 19 -- 18 # 0xfff3ffff + uint32_t reg_gpio_21_pu : 1; // @ 20 -- 20 # 0xffefffff + uint32_t reg_gpio_21_pd : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t pad2 : 2; + uint32_t reg_gpio_21_func_sel : 4; // @ 27 -- 24 # 0xf0ffffff + uint32_t pad3 : 4; + }; + } GPIO_CFGCTL10; // @ 0x128 + union { + uint32_t value; + struct { + uint32_t reg_gpio_22_ie : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t reg_gpio_22_smt : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t reg_gpio_22_drv : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t reg_gpio_22_pu : 1; // @ 4 -- 4 # 0xffffffef + uint32_t reg_gpio_22_pd : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad0 : 2; + uint32_t reg_gpio_22_func_sel : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t pad1 : 4; + uint32_t reg_gpio_23_ie : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t reg_gpio_23_smt : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t reg_gpio_23_drv : 2; // @ 19 -- 18 # 0xfff3ffff + uint32_t reg_gpio_23_pu : 1; // @ 20 -- 20 # 0xffefffff + uint32_t reg_gpio_23_pd : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t pad2 : 10; + }; + } GPIO_CFGCTL11; // @ 0x12c + union { + uint32_t value; + struct { + uint32_t reg_gpio_24_ie : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t reg_gpio_24_smt : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t reg_gpio_24_drv : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t reg_gpio_24_pu : 1; // @ 4 -- 4 # 0xffffffef + uint32_t reg_gpio_24_pd : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad0 : 10; + uint32_t reg_gpio_25_ie : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t reg_gpio_25_smt : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t reg_gpio_25_drv : 2; // @ 19 -- 18 # 0xfff3ffff + uint32_t reg_gpio_25_pu : 1; // @ 20 -- 20 # 0xffefffff + uint32_t reg_gpio_25_pd : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t pad1 : 10; + }; + } GPIO_CFGCTL12; // @ 0x130 + union { + uint32_t value; + struct { + uint32_t reg_gpio_26_ie : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t reg_gpio_26_smt : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t reg_gpio_26_drv : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t reg_gpio_26_pu : 1; // @ 4 -- 4 # 0xffffffef + uint32_t reg_gpio_26_pd : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad0 : 10; + uint32_t reg_gpio_27_ie : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t reg_gpio_27_smt : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t reg_gpio_27_drv : 2; // @ 19 -- 18 # 0xfff3ffff + uint32_t reg_gpio_27_pu : 1; // @ 20 -- 20 # 0xffefffff + uint32_t reg_gpio_27_pd : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t pad1 : 10; + }; + } GPIO_CFGCTL13; // @ 0x134 + union { + uint32_t value; + struct { + uint32_t reg_gpio_28_ie : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t reg_gpio_28_smt : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t reg_gpio_28_drv : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t reg_gpio_28_pu : 1; // @ 4 -- 4 # 0xffffffef + uint32_t reg_gpio_28_pd : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad0 : 26; + }; + } GPIO_CFGCTL14; // @ 0x138 + uint8_t pad6[0x44]; + union { + uint32_t value; + struct { + uint32_t reg_gpio_0_i : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t reg_gpio_1_i : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t reg_gpio_2_i : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t reg_gpio_3_i : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t reg_gpio_4_i : 1; // @ 4 -- 4 # 0xffffffef + uint32_t reg_gpio_5_i : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t reg_gpio_6_i : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t reg_gpio_7_i : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t reg_gpio_8_i : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t reg_gpio_9_i : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t reg_gpio_10_i : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t reg_gpio_11_i : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t reg_gpio_12_i : 1; // @ 12 -- 12 # 0xffffefff + uint32_t reg_gpio_13_i : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t reg_gpio_14_i : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t reg_gpio_15_i : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t reg_gpio_16_i : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t reg_gpio_17_i : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t reg_gpio_18_i : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t reg_gpio_19_i : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t reg_gpio_20_i : 1; // @ 20 -- 20 # 0xffefffff + uint32_t reg_gpio_21_i : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t reg_gpio_22_i : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t pad0 : 9; + }; + } GPIO_CFGCTL30; // @ 0x180 + uint32_t GPIO_CFGCTL31; // @ 0x184 + union { + uint32_t value; + struct { + uint32_t reg_gpio_0_o : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t reg_gpio_1_o : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t reg_gpio_2_o : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t reg_gpio_3_o : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t reg_gpio_4_o : 1; // @ 4 -- 4 # 0xffffffef + uint32_t reg_gpio_5_o : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t reg_gpio_6_o : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t reg_gpio_7_o : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t reg_gpio_8_o : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t reg_gpio_9_o : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t reg_gpio_10_o : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t reg_gpio_11_o : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t reg_gpio_12_o : 1; // @ 12 -- 12 # 0xffffefff + uint32_t reg_gpio_13_o : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t reg_gpio_14_o : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t reg_gpio_15_o : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t reg_gpio_16_o : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t reg_gpio_17_o : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t reg_gpio_18_o : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t reg_gpio_19_o : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t reg_gpio_20_o : 1; // @ 20 -- 20 # 0xffefffff + uint32_t reg_gpio_21_o : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t reg_gpio_22_o : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t pad0 : 9; + }; + } GPIO_CFGCTL32; // @ 0x188 + uint32_t GPIO_CFGCTL33; // @ 0x18c + union { + uint32_t value; + struct { + uint32_t reg_gpio_0_oe : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t reg_gpio_1_oe : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t reg_gpio_2_oe : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t reg_gpio_3_oe : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t reg_gpio_4_oe : 1; // @ 4 -- 4 # 0xffffffef + uint32_t reg_gpio_5_oe : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t reg_gpio_6_oe : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t reg_gpio_7_oe : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t reg_gpio_8_oe : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t reg_gpio_9_oe : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t reg_gpio_10_oe : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t reg_gpio_11_oe : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t reg_gpio_12_oe : 1; // @ 12 -- 12 # 0xffffefff + uint32_t reg_gpio_13_oe : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t reg_gpio_14_oe : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t reg_gpio_15_oe : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t reg_gpio_16_oe : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t reg_gpio_17_oe : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t reg_gpio_18_oe : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t reg_gpio_19_oe : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t reg_gpio_20_oe : 1; // @ 20 -- 20 # 0xffefffff + uint32_t reg_gpio_21_oe : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t reg_gpio_22_oe : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t pad0 : 9; + }; + } GPIO_CFGCTL34; // @ 0x190 + uint32_t GPIO_CFGCTL35; // @ 0x194 + uint8_t pad7[0x8]; + union { + uint32_t value; + struct { + uint32_t reg_gpio_int_mask1 : 32; // @ 31 -- 0 # 0x0 + }; + } GPIO_INT_MASK1; // @ 0x1a0 + uint8_t pad8[0x4]; + union { + uint32_t value; + struct { + uint32_t gpio_int_stat1 : 32; // @ 31 -- 0 # 0x0 + }; + } GPIO_INT_STAT1; // @ 0x1a8 + uint8_t pad9[0x4]; + union { + uint32_t value; + struct { + uint32_t reg_gpio_int_clr1 : 32; // @ 31 -- 0 # 0x0 + }; + } GPIO_INT_CLR1; // @ 0x1b0 + uint8_t pad10[0xc]; + union { + uint32_t value; + struct { + uint32_t reg_gpio_int_mode_set1 : 32; // @ 31 -- 0 # 0x0 + }; + } GPIO_INT_MODE_SET1; // @ 0x1c0 + union { + uint32_t value; + struct { + uint32_t reg_gpio_int_mode_set2 : 32; // @ 31 -- 0 # 0x0 + }; + } GPIO_INT_MODE_SET2; // @ 0x1c4 + union { + uint32_t value; + struct { + uint32_t reg_gpio_int_mode_set3 : 32; // @ 31 -- 0 # 0x0 + }; + } GPIO_INT_MODE_SET3; // @ 0x1c8 + uint8_t pad11[0x58]; + union { + uint32_t value; + struct { + uint32_t led_din_reg : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t led_din_sel : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t led_din_polarity_sel : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 1; + uint32_t leddrv_ibias : 4; // @ 7 -- 4 # 0xffffff0f + uint32_t ir_rx_gpio_sel : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad1 : 21; + uint32_t pu_leddrv : 1; // @ 31 -- 31 # 0x7fffffff + }; + } led_driver; // @ 0x224 + uint8_t pad12[0xe0]; + union { + uint32_t value; + struct { + uint32_t gpdaca_rstn_ana : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t gpdacb_rstn_ana : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t pad0 : 5; + uint32_t gpdac_test_en : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t gpdac_ref_sel : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t gpdac_test_sel : 3; // @ 11 -- 9 # 0xfffff1ff + uint32_t pad1 : 12; + uint32_t gpdac_reserved : 8; // @ 31 -- 24 # 0xffffff + }; + } gpdac_ctrl; // @ 0x308 + union { + uint32_t value; + struct { + uint32_t gpdac_a_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t gpdac_ioa_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t pad0 : 16; + uint32_t gpdac_a_rng : 2; // @ 19 -- 18 # 0xfff3ffff + uint32_t gpdac_a_outmux : 3; // @ 22 -- 20 # 0xff8fffff + uint32_t pad1 : 9; + }; + } gpdac_actrl; // @ 0x30c + union { + uint32_t value; + struct { + uint32_t gpdac_b_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t gpdac_iob_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t pad0 : 16; + uint32_t gpdac_b_rng : 2; // @ 19 -- 18 # 0xfff3ffff + uint32_t gpdac_b_outmux : 3; // @ 22 -- 20 # 0xff8fffff + uint32_t pad1 : 9; + }; + } gpdac_bctrl; // @ 0x310 + union { + uint32_t value; + struct { + uint32_t gpdac_b_data : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t pad0 : 6; + uint32_t gpdac_a_data : 10; // @ 25 -- 16 # 0xfc00ffff + uint32_t pad1 : 6; + }; + } gpdac_data; // @ 0x314 + uint8_t pad13[0xbe8]; + union { + uint32_t value; + struct { + uint32_t tzc_glb_swrst_s00_lock : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t tzc_glb_swrst_s01_lock : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t pad0 : 6; + uint32_t tzc_glb_swrst_s30_lock : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pad1 : 3; + uint32_t tzc_glb_ctrl_pwron_rst_lock : 1; // @ 12 -- 12 # 0xffffefff + uint32_t tzc_glb_ctrl_cpu_reset_lock : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t tzc_glb_ctrl_sys_reset_lock : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t tzc_glb_ctrl_ungated_ap_lock : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t pad2 : 9; + uint32_t tzc_glb_misc_lock : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t tzc_glb_sram_lock : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t tzc_glb_l2c_lock : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t tzc_glb_bmx_lock : 1; // @ 28 -- 28 # 0xefffffff + uint32_t tzc_glb_dbg_lock : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t tzc_glb_mbist_lock : 1; // @ 30 -- 30 # 0xbfffffff + uint32_t tzc_glb_clk_lock : 1; // @ 31 -- 31 # 0x7fffffff + }; + } tzc_glb_ctrl_0; // @ 0xf00 + union { + uint32_t value; + struct { + uint32_t tzc_glb_swrst_s20_lock : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t tzc_glb_swrst_s21_lock : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t tzc_glb_swrst_s22_lock : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t tzc_glb_swrst_s23_lock : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t tzc_glb_swrst_s24_lock : 1; // @ 4 -- 4 # 0xffffffef + uint32_t tzc_glb_swrst_s25_lock : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t tzc_glb_swrst_s26_lock : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t tzc_glb_swrst_s27_lock : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t tzc_glb_swrst_s28_lock : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t tzc_glb_swrst_s29_lock : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t tzc_glb_swrst_s2a_lock : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t tzc_glb_swrst_s2b_lock : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t tzc_glb_swrst_s2c_lock : 1; // @ 12 -- 12 # 0xffffefff + uint32_t tzc_glb_swrst_s2d_lock : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t tzc_glb_swrst_s2e_lock : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t tzc_glb_swrst_s2f_lock : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t tzc_glb_swrst_s10_lock : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t tzc_glb_swrst_s11_lock : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t tzc_glb_swrst_s12_lock : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t tzc_glb_swrst_s13_lock : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t tzc_glb_swrst_s14_lock : 1; // @ 20 -- 20 # 0xffefffff + uint32_t tzc_glb_swrst_s15_lock : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t tzc_glb_swrst_s16_lock : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t tzc_glb_swrst_s17_lock : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t tzc_glb_swrst_s18_lock : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t tzc_glb_swrst_s19_lock : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t tzc_glb_swrst_s1a_lock : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t tzc_glb_swrst_s1b_lock : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t tzc_glb_swrst_s1c_lock : 1; // @ 28 -- 28 # 0xefffffff + uint32_t tzc_glb_swrst_s1d_lock : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t tzc_glb_swrst_s1e_lock : 1; // @ 30 -- 30 # 0xbfffffff + uint32_t tzc_glb_swrst_s1f_lock : 1; // @ 31 -- 31 # 0x7fffffff + }; + } tzc_glb_ctrl_1; // @ 0xf04 + union { + uint32_t value; + struct { + uint32_t tzc_glb_gpio_0_lock : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t tzc_glb_gpio_1_lock : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t tzc_glb_gpio_2_lock : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t tzc_glb_gpio_3_lock : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t tzc_glb_gpio_4_lock : 1; // @ 4 -- 4 # 0xffffffef + uint32_t tzc_glb_gpio_5_lock : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t tzc_glb_gpio_6_lock : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t tzc_glb_gpio_7_lock : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t tzc_glb_gpio_8_lock : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t tzc_glb_gpio_9_lock : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t tzc_glb_gpio_10_lock : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t tzc_glb_gpio_11_lock : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t tzc_glb_gpio_12_lock : 1; // @ 12 -- 12 # 0xffffefff + uint32_t tzc_glb_gpio_13_lock : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t tzc_glb_gpio_14_lock : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t tzc_glb_gpio_15_lock : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t tzc_glb_gpio_16_lock : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t tzc_glb_gpio_17_lock : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t tzc_glb_gpio_18_lock : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t tzc_glb_gpio_19_lock : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t tzc_glb_gpio_20_lock : 1; // @ 20 -- 20 # 0xffefffff + uint32_t tzc_glb_gpio_21_lock : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t tzc_glb_gpio_22_lock : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t tzc_glb_gpio_23_lock : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t tzc_glb_gpio_24_lock : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t tzc_glb_gpio_25_lock : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t tzc_glb_gpio_26_lock : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t tzc_glb_gpio_27_lock : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t tzc_glb_gpio_28_lock : 1; // @ 28 -- 28 # 0xefffffff + uint32_t pad0 : 3; + }; + } tzc_glb_ctrl_2; // @ 0xf08 + uint32_t tzc_glb_ctrl_3; // @ 0xf0c + }; +} glb_regs; +#define GLB_BASE 0x40000000 +#define GLB ((glb_regs* volatile)(GLB_BASE)) \ No newline at end of file diff --git a/src/include/soc/rf.h b/src/include/soc/rf.h new file mode 100644 index 0000000..a0061d4 --- /dev/null +++ b/src/include/soc/rf.h @@ -0,0 +1,1921 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + union { + uint32_t value; + struct { + uint32_t rf_id : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t fw_rev : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t hw_rev : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t pad0 : 8; + }; + } rf_rev; // @ 0x0 + union { + uint32_t value; + struct { + uint32_t pad0 : 1; + uint32_t rf_fsm_ctrl_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t rf_fsm_t2r_cal_mode : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t rf_fsm_state : 3; // @ 6 -- 4 # 0xffffff8f + uint32_t pad1 : 1; + uint32_t rf_rc_state_dbg : 3; // @ 10 -- 8 # 0xfffff8ff + uint32_t rf_rc_state_dbg_en : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t rf_fsm_st_int_sel : 3; // @ 14 -- 12 # 0xffff8fff + uint32_t pad2 : 1; + uint32_t rf_fsm_st_int : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad3 : 3; + uint32_t rf_fsm_st_int_clr : 1; // @ 20 -- 20 # 0xffefffff + uint32_t pad4 : 3; + uint32_t rf_fsm_st_int_set : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t pad5 : 3; + uint32_t rf_rc_state_value : 3; // @ 30 -- 28 # 0x8fffffff + uint32_t pad6 : 1; + }; + } rf_fsm_ctrl_hw; // @ 0x4 + union { + uint32_t value; + struct { + uint32_t rf_fsm_sw_st : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t pad0 : 3; + uint32_t rf_fsm_sw_st_vld : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pad1 : 3; + uint32_t full_cal_en : 1; // @ 12 -- 12 # 0xffffefff + uint32_t pad2 : 3; + uint32_t inc_cal_timeout : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad3 : 3; + uint32_t lo_unlocked : 1; // @ 20 -- 20 # 0xffefffff + uint32_t pad4 : 11; + }; + } rf_fsm_ctrl_sw; // @ 0x8 + union { + uint32_t value; + struct { + uint32_t pu_ctrl_hw : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t rx_gain_ctrl_hw : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t tx_gain_ctrl_hw : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t lna_ctrl_hw : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t rbb_bw_ctrl_hw : 1; // @ 4 -- 4 # 0xffffffef + uint32_t trxcal_ctrl_hw : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t lo_ctrl_hw : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t inc_acal_ctrl_en_hw : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t inc_fcal_ctrl_en_hw : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t sdm_ctrl_hw : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t rbb_pkdet_en_ctrl_hw : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t rbb_pkdet_out_rstn_ctrl_hw : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t adda_ctrl_hw : 1; // @ 12 -- 12 # 0xffffefff + uint32_t pad0 : 19; + }; + } rfctrl_hw_en; // @ 0xc + union { + uint32_t value; + struct { + uint32_t const_acal : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t const_fcal : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t temp_comp_en : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad0 : 15; + }; + } temp_comp; // @ 0x10 + union { + uint32_t value; + struct { + uint32_t rcal_status : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t adc_oscal_status : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t fcal_status : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t acal_status : 2; // @ 7 -- 6 # 0xffffff3f + uint32_t inc_fcal_status : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t inc_acal_status : 2; // @ 11 -- 10 # 0xfffff3ff + uint32_t clkpll_cal_status : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t ros_status : 2; // @ 15 -- 14 # 0xffff3fff + uint32_t tos_status : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t rccal_status : 2; // @ 19 -- 18 # 0xfff3ffff + uint32_t lo_leakcal_status : 2; // @ 21 -- 20 # 0xffcfffff + uint32_t tiqcal_status_resv : 2; // @ 23 -- 22 # 0xff3fffff + uint32_t riqcal_status_resv : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t pwdet_cal_status : 2; // @ 27 -- 26 # 0xf3ffffff + uint32_t tenscal_status : 2; // @ 29 -- 28 # 0xcfffffff + uint32_t dpd_status : 2; // @ 31 -- 30 # 0x3fffffff + }; + } rfcal_status; // @ 0x14 + union { + uint32_t value; + struct { + uint32_t dl_rfcal_table_status : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 30; + }; + } rfcal_status2; // @ 0x18 + union { + uint32_t value; + struct { + uint32_t rcal_en_resv : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t adc_oscal_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t dl_rfcal_table_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t fcal_en : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t acal_en : 1; // @ 4 -- 4 # 0xffffffef + uint32_t fcal_inc_en : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t acal_inc_en : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t roscal_inc_en : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t clkpll_cal_en : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t roscal_en : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t toscal_en : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t rccal_en : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t lo_leakcal_en : 1; // @ 12 -- 12 # 0xffffefff + uint32_t tiqcal_en : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t riqcal_en : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t pwdet_cal_en : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t tsencal_en : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t dpd_en : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t pad0 : 14; + }; + } rfcal_ctrlen; // @ 0x1c + union { + uint32_t value; + struct { + uint32_t rcal_sten_resv : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t adc_oscal_sten : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t dl_rfcal_table_sten : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t fcal_sten : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t acal_sten : 1; // @ 4 -- 4 # 0xffffffef + uint32_t inc_fcal_sten : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t inc_acal_sten : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t clkpll_cal_sten : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t roscal_sten : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t toscal_sten_resv : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t rccal_sten : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t lo_leakcal_sten : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t tiqcal_sten : 1; // @ 12 -- 12 # 0xffffefff + uint32_t riqcal_sten : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t pwdet_cal_sten : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t tsencal_sten : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t dpd_sten : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad0 : 13; + uint32_t rfcal_level : 2; // @ 31 -- 30 # 0x3fffffff + }; + } rfcal_stateen; // @ 0x20 + uint32_t saradc_resv; // @ 0x24 + union { + uint32_t value; + struct { + uint32_t aupll_sdm_rst_dly : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t lo_sdm_rst_dly : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t pad0 : 4; + uint32_t ppu_lead : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pud_vco_dly : 2; // @ 11 -- 10 # 0xfffff3ff + uint32_t pud_iref_dly : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t pud_pa_dly : 2; // @ 15 -- 14 # 0xffff3fff + uint32_t pad1 : 11; + uint32_t mbg_trim : 2; // @ 28 -- 27 # 0xe7ffffff + uint32_t pad2 : 3; + }; + } rf_base_ctrl1; // @ 0x28 + uint32_t rf_base_ctrl2; // @ 0x2c + union { + uint32_t value; + struct { + uint32_t pu_sfreg : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 7; + uint32_t pu_lna : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pu_rmxgm : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t pu_rmx : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t pu_rbb : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t pu_adda_ldo : 1; // @ 12 -- 12 # 0xffffefff + uint32_t adc_clk_en : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t pu_adc : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t pu_op_atest : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t pu_pa : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pu_tmx : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t pu_tbb : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t pu_dac : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t pu_vco : 1; // @ 20 -- 20 # 0xffefffff + uint32_t pu_fbdv : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t pu_pfd : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t pu_osmx : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t pu_rxbuf : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t pu_txbuf : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t trsw_en : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t pad1 : 1; + uint32_t pu_pkdet : 1; // @ 28 -- 28 # 0xefffffff + uint32_t pu_rosdac : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t pu_pwrmx : 1; // @ 30 -- 30 # 0xbfffffff + uint32_t pu_tosdac : 1; // @ 31 -- 31 # 0x7fffffff + }; + } pucr1; // @ 0x30 + union { + uint32_t value; + struct { + uint32_t pu_sfreg_hw : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 7; + uint32_t pu_lna_hw : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pu_rmxgm_hw : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t pu_rmx_hw : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t pu_rbb_hw : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t pu_adda_ldo_hw : 1; // @ 12 -- 12 # 0xffffefff + uint32_t adc_clk_en_hw : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t pu_adc_hw : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t pad1 : 1; + uint32_t pu_pa_hw : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pu_tmx_hw : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t pu_tbb_hw : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t pu_dac_hw : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t pu_vco_hw : 1; // @ 20 -- 20 # 0xffefffff + uint32_t pu_fbdv_hw : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t pu_pfd_hw : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t pu_osmx_hw : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t pu_rxbuf_hw : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t pu_txbuf_hw : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t trsw_en_hw : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t pad2 : 1; + uint32_t pu_pkdet_hw : 1; // @ 28 -- 28 # 0xefffffff + uint32_t pu_rosdac_hw : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t pad3 : 1; + uint32_t pu_tosdac_hw : 1; // @ 31 -- 31 # 0x7fffffff + }; + } pucr1_hw; // @ 0x34 + uint32_t pucr2; // @ 0x38 + uint32_t pucr2_hw; // @ 0x3c + union { + uint32_t value; + struct { + uint32_t pad0 : 8; + uint32_t ppu_lna_hw : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t ppu_rmxgm_hw : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t pad1 : 1; + uint32_t ppu_rbb_hw : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t pad2 : 8; + uint32_t ppu_vco_hw : 1; // @ 20 -- 20 # 0xffefffff + uint32_t ppu_fbdv_hw : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t ppu_pfd_hw : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t ppu_osmx_hw : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t ppu_rxbuf_hw : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t ppu_txbuf_hw : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t pad3 : 6; + }; + } ppu_ctrl_hw; // @ 0x40 + union { + uint32_t value; + struct { + uint32_t pad0 : 20; + uint32_t pud_vco_hw : 1; // @ 20 -- 20 # 0xffefffff + uint32_t pad1 : 11; + }; + } pud_ctrl_hw; // @ 0x44 + union { + uint32_t value; + struct { + uint32_t gc_lna : 3; // @ 2 -- 0 # 0xfffffff8 + uint32_t pad0 : 1; + uint32_t gc_rmxgm : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t pad1 : 2; + uint32_t gc_rbb1 : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad2 : 2; + uint32_t gc_rbb2 : 3; // @ 14 -- 12 # 0xffff8fff + uint32_t pad3 : 1; + uint32_t gc_tmx : 3; // @ 18 -- 16 # 0xfff8ffff + uint32_t pad4 : 1; + uint32_t gc_tbb : 5; // @ 24 -- 20 # 0xfe0fffff + uint32_t pad5 : 3; + uint32_t gc_tbb_boost : 2; // @ 29 -- 28 # 0xcfffffff + uint32_t pad6 : 2; + }; + } trx_gain1; // @ 0x48 + union { + uint32_t value; + struct { + uint32_t gc_lna_hw : 3; // @ 2 -- 0 # 0xfffffff8 + uint32_t pad0 : 1; + uint32_t gc_rmxgm_hw : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t pad1 : 2; + uint32_t gc_rbb1_hw : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad2 : 2; + uint32_t gc_rbb2_hw : 3; // @ 14 -- 12 # 0xffff8fff + uint32_t pad3 : 1; + uint32_t gc_tmx_hw : 3; // @ 18 -- 16 # 0xfff8ffff + uint32_t pad4 : 1; + uint32_t gc_tbb_hw : 5; // @ 24 -- 20 # 0xfe0fffff + uint32_t pad5 : 3; + uint32_t gc_tbb_boost_hw : 2; // @ 29 -- 28 # 0xcfffffff + uint32_t pad6 : 2; + }; + } trx_gain_hw; // @ 0x4c + union { + uint32_t value; + struct { + uint32_t tmux : 3; // @ 2 -- 0 # 0xfffffff8 + uint32_t dc_tp_en : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t dc_tp_clkpll_en : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pad0 : 3; + uint32_t ten_clkpll : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t ten_clkpll_sfreg : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t pad1 : 2; + uint32_t ten_rrf_0 : 1; // @ 12 -- 12 # 0xffffefff + uint32_t ten_rrf_1 : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t ten_pa : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t ten_tmx : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t ten_tia : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t ten_bq : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t ten_atest : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t ten_tbb : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t ten_adc : 1; // @ 20 -- 20 # 0xffefffff + uint32_t ten_dac_i : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t ten_dac_q : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t pad2 : 1; + uint32_t ten_vco : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t ten_pfdcp : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t ten_lf : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t ten_lodist : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t pad3 : 4; + }; + } ten_dc; // @ 0x50 + union { + uint32_t value; + struct { + uint32_t dten_clkpll_postdiv_clk : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t dten_clkpll_clk96m : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t dten_clkpll_clk32m : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t dten_clkpll_fsdm : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t dten_clkpll_fref : 1; // @ 4 -- 4 # 0xffffffef + uint32_t dten_clkpll_fin : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t dten_lo_fsdm : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t pad0 : 1; + uint32_t dten_lo_fref : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t dtest_pull_down : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t pad1 : 13; + uint32_t rf_dtest_en : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t pad2 : 8; + }; + } ten_dig; // @ 0x54 + union { + uint32_t value; + struct { + uint32_t atest_op_cc : 4; // @ 3 -- 0 # 0xfffffff0 + uint32_t atest_dac_en : 1; // @ 4 -- 4 # 0xffffffef + uint32_t atest_in_trx_sw : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t atest_in_en : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t pad0 : 1; + uint32_t atest_gain_r9 : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t atest_gain_r8 : 2; // @ 11 -- 10 # 0xfffff3ff + uint32_t atest_gain_r7 : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t atest_gain_r6 : 2; // @ 15 -- 14 # 0xffff3fff + uint32_t atest_gain_r5 : 3; // @ 18 -- 16 # 0xfff8ffff + uint32_t pad1 : 1; + uint32_t atest_out_en_q : 1; // @ 20 -- 20 # 0xffefffff + uint32_t atest_out_en_i : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t atest_in_en_q : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t atest_in_en_i : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t pad2 : 8; + }; + } ten_ac; // @ 0x58 + uint32_t pmip_mv2aon; // @ 0x5c + union { + uint32_t value; + struct { + uint32_t vg11_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t vg13_sel : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t pad0 : 28; + }; + } cip; // @ 0x60 + union { + uint32_t value; + struct { + uint32_t pa_iaq : 3; // @ 2 -- 0 # 0xfffffff8 + uint32_t pa_etb_en : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pa_iet : 4; // @ 7 -- 4 # 0xffffff0f + uint32_t pa_vbcore : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t pa_vbcas : 3; // @ 14 -- 12 # 0xffff8fff + uint32_t pa_half_on : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t pa_ib_fix : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pa_lz_bias_en : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t pa_pwrmx_osdac : 4; // @ 21 -- 18 # 0xffc3ffff + uint32_t pa_pwrmx_dac_pn_switch : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t pad0 : 1; + uint32_t pa_pwrmx_bm : 3; // @ 26 -- 24 # 0xf8ffffff + uint32_t pad1 : 1; + uint32_t pa_att_gc : 4; // @ 31 -- 28 # 0xfffffff + }; + } pa1; // @ 0x64 + union { + uint32_t value; + struct { + uint32_t pad0 : 3; + uint32_t pa_etb_en_hw : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pa_iet_hw : 4; // @ 7 -- 4 # 0xffffff0f + uint32_t pa_vbcore_hw : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t pa_vbcas_hw : 3; // @ 14 -- 12 # 0xffff8fff + uint32_t pad1 : 1; + uint32_t pa_half_on_hw : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pa_ib_fix_hw : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t pad2 : 14; + }; + } pa2; // @ 0x68 + union { + uint32_t value; + struct { + uint32_t tmx_cs : 3; // @ 2 -- 0 # 0xfffffff8 + uint32_t pad0 : 1; + uint32_t tmx_bm_sw : 3; // @ 6 -- 4 # 0xffffff8f + uint32_t pad1 : 1; + uint32_t tmx_bm_cas : 3; // @ 10 -- 8 # 0xfffff8ff + uint32_t pad2 : 1; + uint32_t tmx_bm_cas_bulk : 3; // @ 14 -- 12 # 0xffff8fff + uint32_t pad3 : 1; + uint32_t tx_tsense_en : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad4 : 15; + }; + } tmx; // @ 0x6c + union { + uint32_t value; + struct { + uint32_t tbb_bm_sf : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 2; + uint32_t tbb_bm_cg : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t pad1 : 2; + uint32_t tbb_vcm : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad2 : 2; + uint32_t tbb_cflt : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t tbb_iq_bias_short : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t tbb_atest_out_en : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t tbb_tosdac_q : 6; // @ 21 -- 16 # 0xffc0ffff + uint32_t pad3 : 2; + uint32_t tbb_tosdac_i : 6; // @ 29 -- 24 # 0xc0ffffff + uint32_t pad4 : 2; + }; + } tbb; // @ 0x70 + union { + uint32_t value; + struct { + uint32_t lna_bm : 4; // @ 3 -- 0 # 0xfffffff0 + uint32_t lna_bm_hw : 4; // @ 7 -- 4 # 0xffffff0f + uint32_t lna_load_csw : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t lna_load_csw_hw : 4; // @ 15 -- 12 # 0xffff0fff + uint32_t lna_rfb_match : 3; // @ 18 -- 16 # 0xfff8ffff + uint32_t pad0 : 1; + uint32_t lna_cap_lg : 2; // @ 21 -- 20 # 0xffcfffff + uint32_t pad1 : 2; + uint32_t lna_lg_gsel : 3; // @ 26 -- 24 # 0xf8ffffff + uint32_t pad2 : 5; + }; + } lna; // @ 0x74 + union { + uint32_t value; + struct { + uint32_t rmx_bm : 3; // @ 2 -- 0 # 0xfffffff8 + uint32_t pad0 : 1; + uint32_t rmxgm_bm : 3; // @ 6 -- 4 # 0xffffff8f + uint32_t pad1 : 1; + uint32_t rmxgm_10m_mode_en : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pad2 : 23; + }; + } rmxgm; // @ 0x78 + union { + uint32_t value; + struct { + uint32_t rosdac_q : 6; // @ 5 -- 0 # 0xffffffc0 + uint32_t pad0 : 2; + uint32_t rosdac_i : 6; // @ 13 -- 8 # 0xffffc0ff + uint32_t pad1 : 2; + uint32_t rosdac_q_hw : 6; // @ 21 -- 16 # 0xffc0ffff + uint32_t pad2 : 2; + uint32_t rosdac_i_hw : 6; // @ 29 -- 24 # 0xc0ffffff + uint32_t pad3 : 1; + uint32_t rosdac_range : 1; // @ 31 -- 31 # 0x7fffffff + }; + } rbb1; // @ 0x7c + union { + uint32_t value; + struct { + uint32_t rbb_cap2_fc_q : 6; // @ 5 -- 0 # 0xffffffc0 + uint32_t pad0 : 2; + uint32_t rbb_cap2_fc_i : 6; // @ 13 -- 8 # 0xffffc0ff + uint32_t pad1 : 2; + uint32_t rbb_cap1_fc_q : 6; // @ 21 -- 16 # 0xffc0ffff + uint32_t pad2 : 2; + uint32_t rbb_cap1_fc_i : 6; // @ 29 -- 24 # 0xc0ffffff + uint32_t pad3 : 2; + }; + } rbb2; // @ 0x80 + union { + uint32_t value; + struct { + uint32_t rbb_bt_mode_hw : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 3; + uint32_t rbb_bt_mode : 1; // @ 4 -- 4 # 0xffffffef + uint32_t rbb_bt_fif_tune : 2; // @ 6 -- 5 # 0xffffff9f + uint32_t pad1 : 1; + uint32_t rbb_deq : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad2 : 2; + uint32_t rbb_bm_op : 3; // @ 14 -- 12 # 0xffff8fff + uint32_t pad3 : 1; + uint32_t rbb_vcm : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad4 : 2; + uint32_t rbb_bq_iqbias_short : 1; // @ 20 -- 20 # 0xffefffff + uint32_t rbb_tia_iqbias_short : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t pad5 : 2; + uint32_t rbb_bw : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t pad6 : 2; + uint32_t rxiqcal_en : 1; // @ 28 -- 28 # 0xefffffff + uint32_t pad7 : 2; + uint32_t pwr_det_en : 1; // @ 31 -- 31 # 0x7fffffff + }; + } rbb3; // @ 0x84 + union { + uint32_t value; + struct { + uint32_t rbb_pkdet_vth : 4; // @ 3 -- 0 # 0xfffffff0 + uint32_t rbb_pkdet_out_rstn : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pad0 : 3; + uint32_t rbb_pkdet_en : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pad1 : 3; + uint32_t rbb_pkdet_out_rstn_hw : 1; // @ 12 -- 12 # 0xffffefff + uint32_t pad2 : 3; + uint32_t rbb_pkdet_en_hw : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad3 : 3; + uint32_t pkdet_out_raw : 1; // @ 20 -- 20 # 0xffefffff + uint32_t pad4 : 3; + uint32_t pkdet_out_latch : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t pad5 : 7; + }; + } rbb4; // @ 0x88 + union { + uint32_t value; + struct { + uint32_t dac_dvdd_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 2; + uint32_t dac_bias_sel : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t pad1 : 2; + uint32_t dac_clk_sel : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad2 : 2; + uint32_t dac_rccalsel : 1; // @ 12 -- 12 # 0xffffefff + uint32_t dac_clk_sync_inv : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t pad3 : 2; + uint32_t adda_ldo_byps : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad4 : 3; + uint32_t adda_ldo_dvdd_sel : 3; // @ 22 -- 20 # 0xff8fffff + uint32_t pad5 : 1; + uint32_t adda_ldo_dvdd_sel_hw : 3; // @ 26 -- 24 # 0xf8ffffff + uint32_t pad6 : 5; + }; + } adda1; // @ 0x8c + union { + uint32_t value; + struct { + uint32_t adc_vref_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 2; + uint32_t adc_dly_ctl : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t pad1 : 2; + uint32_t adc_dvdd_sel : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad2 : 2; + uint32_t adc_sar_ascal_en : 1; // @ 12 -- 12 # 0xffffefff + uint32_t pad3 : 3; + uint32_t adc_gt_rm : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad4 : 3; + uint32_t adc_clk_sync_inv : 1; // @ 20 -- 20 # 0xffefffff + uint32_t pad5 : 3; + uint32_t adc_clk_inv : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t pad6 : 3; + uint32_t adc_clk_div_sel : 1; // @ 28 -- 28 # 0xefffffff + uint32_t pad7 : 3; + }; + } adda2; // @ 0x90 + uint8_t pad0[0xc]; + union { + uint32_t value; + struct { + uint32_t lo_vco_freq_cw : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t lo_vco_freq_cw_hw : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t lo_vco_idac_cw : 5; // @ 20 -- 16 # 0xffe0ffff + uint32_t pad0 : 3; + uint32_t lo_vco_idac_cw_hw : 5; // @ 28 -- 24 # 0xe0ffffff + uint32_t pad1 : 3; + }; + } vco1; // @ 0xa0 + union { + uint32_t value; + struct { + uint32_t lo_vco_vbias_cw : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 2; + uint32_t lo_vco_idac_boot : 1; // @ 4 -- 4 # 0xffffffef + uint32_t lo_vco_short_vbias_filter : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t lo_vco_short_idac_filter : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t pad1 : 1; + uint32_t acal_vref_cw : 3; // @ 10 -- 8 # 0xfffff8ff + uint32_t pad2 : 1; + uint32_t acal_vco_ud : 1; // @ 12 -- 12 # 0xffffefff + uint32_t pad3 : 3; + uint32_t acal_inc_en_hw : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad4 : 15; + }; + } vco2; // @ 0xa4 + union { + uint32_t value; + struct { + uint32_t fcal_div : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t fcal_cnt_op : 16; // @ 31 -- 16 # 0xffff + }; + } vco3; // @ 0xa8 + union { + uint32_t value; + struct { + uint32_t pad0 : 4; + uint32_t fcal_cnt_start : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pad1 : 3; + uint32_t fcal_inc_en_hw : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pad2 : 7; + uint32_t fcal_inc_large_range : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad3 : 3; + uint32_t fcal_cnt_rdy : 1; // @ 20 -- 20 # 0xffefffff + uint32_t pad4 : 3; + uint32_t fcal_inc_vctrl_ud : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t pad5 : 6; + }; + } vco4; // @ 0xac + union { + uint32_t value; + struct { + uint32_t lo_cp_sel : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 3; + uint32_t lo_cp_sel_hw : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pad1 : 3; + uint32_t lo_cp_startup_en : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pad2 : 3; + uint32_t lo_cp_ota_en : 1; // @ 12 -- 12 # 0xffffefff + uint32_t pad3 : 3; + uint32_t lo_cp_opamp_en : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad4 : 3; + uint32_t lo_cp_hiz : 1; // @ 20 -- 20 # 0xffefffff + uint32_t pad5 : 3; + uint32_t lo_pfd_rvdd_boost : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t pad6 : 3; + uint32_t lo_pfd_rst_csd : 1; // @ 28 -- 28 # 0xefffffff + uint32_t lo_pfd_rst_csd_hw : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t pad7 : 2; + }; + } pfdcp; // @ 0xb0 + union { + uint32_t value; + struct { + uint32_t lo_lf_rz_hw : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 2; + uint32_t lo_lf_r4_hw : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t pad1 : 2; + uint32_t lo_lf_cz_hw : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad2 : 2; + uint32_t lo_lf_rz : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t lo_lf_cz : 2; // @ 15 -- 14 # 0xffff3fff + uint32_t lo_lf_r4 : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t lo_lf_r4_short : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t pad3 : 1; + uint32_t lo_slipped_dn : 1; // @ 20 -- 20 # 0xffefffff + uint32_t pad4 : 3; + uint32_t lo_slipped_up : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t pad5 : 7; + }; + } lo; // @ 0xb4 + union { + uint32_t value; + struct { + uint32_t lo_fbdv_halfstep_en_hw : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 3; + uint32_t lo_fbdv_halfstep_en : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pad1 : 3; + uint32_t lo_fbdv_sel_sample_clk : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad2 : 2; + uint32_t lo_fbdv_sel_fb_clk : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t pad3 : 2; + uint32_t lo_fbdv_rst : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad4 : 3; + uint32_t lo_fbdv_rst_hw : 1; // @ 20 -- 20 # 0xffefffff + uint32_t pad5 : 11; + }; + } fbdv; // @ 0xb8 + union { + uint32_t value; + struct { + uint32_t lo_osmx_xgm_boost : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 3; + uint32_t lo_osmx_en_xgm : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pad1 : 3; + uint32_t lo_osmx_fix_cap : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pad2 : 3; + uint32_t lo_osmx_vbuf_stre : 1; // @ 12 -- 12 # 0xffffefff + uint32_t pad3 : 3; + uint32_t lo_osmx_capbank_bias : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad4 : 2; + uint32_t lo_osmx_cap : 4; // @ 23 -- 20 # 0xff0fffff + uint32_t lo_lodist_txbuf_stre : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t pad5 : 3; + uint32_t lo_lodist_rxbuf_stre : 1; // @ 28 -- 28 # 0xefffffff + uint32_t pad6 : 3; + }; + } lodist; // @ 0xbc + union { + uint32_t value; + struct { + uint32_t lo_sdm_dither_sel_hw : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 2; + uint32_t lo_sdm_bypass_hw : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pad1 : 3; + uint32_t lo_sdm_dither_sel : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad2 : 2; + uint32_t lo_sdm_bypass : 1; // @ 12 -- 12 # 0xffffefff + uint32_t pad3 : 3; + uint32_t lo_sdm_rstb : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t lo_sdm_rstb_hw : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t pad4 : 2; + uint32_t lo_sdm_flag : 1; // @ 20 -- 20 # 0xffefffff + uint32_t pad5 : 11; + }; + } sdm1; // @ 0xc0 + union { + uint32_t value; + struct { + uint32_t lo_sdmin : 30; // @ 29 -- 0 # 0xc0000000 + uint32_t pad0 : 2; + }; + } sdm2; // @ 0xc4 + union { + uint32_t value; + struct { + uint32_t lo_sdmin_hw : 30; // @ 29 -- 0 # 0xc0000000 + uint32_t pad0 : 2; + }; + } sdm3; // @ 0xc8 + uint8_t pad1[0x20]; + union { + uint32_t value; + struct { + uint32_t rf_reserved0 : 32; // @ 31 -- 0 # 0x0 + }; + } rf_resv_reg_0; // @ 0xec + union { + uint32_t value; + struct { + uint32_t rf_reserved1 : 32; // @ 31 -- 0 # 0x0 + }; + } rf_resv_reg_1; // @ 0xf0 + union { + uint32_t value; + struct { + uint32_t rf_reserved2 : 32; // @ 31 -- 0 # 0x0 + }; + } rf_resv_reg_2; // @ 0xf4 + union { + uint32_t value; + struct { + uint32_t gain_ctrl0_gc_rmxgm : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t gain_ctrl0_gc_lna : 3; // @ 4 -- 2 # 0xffffffe3 + uint32_t gain_ctrl1_gc_rmxgm : 2; // @ 6 -- 5 # 0xffffff9f + uint32_t gain_ctrl1_gc_lna : 3; // @ 9 -- 7 # 0xfffffc7f + uint32_t gain_ctrl2_gc_rmxgm : 2; // @ 11 -- 10 # 0xfffff3ff + uint32_t gain_ctrl2_gc_lna : 3; // @ 14 -- 12 # 0xffff8fff + uint32_t gain_ctrl3_gc_rmxgm : 2; // @ 16 -- 15 # 0xfffe7fff + uint32_t gain_ctrl3_gc_lna : 3; // @ 19 -- 17 # 0xfff1ffff + uint32_t gain_ctrl4_gc_rmxgm : 2; // @ 21 -- 20 # 0xffcfffff + uint32_t gain_ctrl4_gc_lna : 3; // @ 24 -- 22 # 0xfe3fffff + uint32_t gain_ctrl5_gc_rmxgm : 2; // @ 26 -- 25 # 0xf9ffffff + uint32_t gain_ctrl5_gc_lna : 3; // @ 29 -- 27 # 0xc7ffffff + uint32_t pad0 : 2; + }; + } rrf_gain_index1; // @ 0xf8 + union { + uint32_t value; + struct { + uint32_t gain_ctrl8_gc_rmxgm : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t gain_ctrl8_gc_lna : 3; // @ 4 -- 2 # 0xffffffe3 + uint32_t gain_ctrl7_gc_rmxgm : 2; // @ 6 -- 5 # 0xffffff9f + uint32_t gain_ctrl7_gc_lna : 3; // @ 9 -- 7 # 0xfffffc7f + uint32_t gain_ctrl6_gc_rmxgm : 2; // @ 11 -- 10 # 0xfffff3ff + uint32_t gain_ctrl6_gc_lna : 3; // @ 14 -- 12 # 0xffff8fff + uint32_t pad0 : 17; + }; + } rrf_gain_index2; // @ 0xfc + union { + uint32_t value; + struct { + uint32_t lna_bm_hg : 4; // @ 3 -- 0 # 0xfffffff0 + uint32_t lna_bm_lg : 4; // @ 7 -- 4 # 0xffffff0f + uint32_t lna_load_csw_hg : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t lna_load_csw_lg : 4; // @ 15 -- 12 # 0xffff0fff + uint32_t pad0 : 16; + }; + } lna_ctrl_hw_mux; // @ 0x100 + union { + uint32_t value; + struct { + uint32_t gain_ctrl0_gc_rbb1 : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 2; + uint32_t gain_ctrl0_gc_rbb2 : 3; // @ 6 -- 4 # 0xffffff8f + uint32_t pad1 : 1; + uint32_t gain_ctrl1_gc_rbb1 : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad2 : 2; + uint32_t gain_ctrl1_gc_rbb2 : 3; // @ 14 -- 12 # 0xffff8fff + uint32_t pad3 : 1; + uint32_t gain_ctrl2_gc_rbb1 : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad4 : 2; + uint32_t gain_ctrl2_gc_rbb2 : 3; // @ 22 -- 20 # 0xff8fffff + uint32_t pad5 : 1; + uint32_t gain_ctrl3_gc_rbb1 : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t pad6 : 2; + uint32_t gain_ctrl3_gc_rbb2 : 3; // @ 30 -- 28 # 0x8fffffff + uint32_t pad7 : 1; + }; + } rbb_gain_index1; // @ 0x104 + union { + uint32_t value; + struct { + uint32_t gain_ctrl4_gc_rbb1 : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 2; + uint32_t gain_ctrl4_gc_rbb2 : 3; // @ 6 -- 4 # 0xffffff8f + uint32_t pad1 : 1; + uint32_t gain_ctrl5_gc_rbb1 : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad2 : 2; + uint32_t gain_ctrl5_gc_rbb2 : 3; // @ 14 -- 12 # 0xffff8fff + uint32_t pad3 : 1; + uint32_t gain_ctrl6_gc_rbb1 : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad4 : 2; + uint32_t gain_ctrl6_gc_rbb2 : 3; // @ 22 -- 20 # 0xff8fffff + uint32_t pad5 : 1; + uint32_t gain_ctrl7_gc_rbb1 : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t pad6 : 2; + uint32_t gain_ctrl7_gc_rbb2 : 3; // @ 30 -- 28 # 0x8fffffff + uint32_t pad7 : 1; + }; + } rbb_gain_index2; // @ 0x108 + union { + uint32_t value; + struct { + uint32_t gain_ctrl8_gc_rbb1 : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 2; + uint32_t gain_ctrl8_gc_rbb2 : 3; // @ 6 -- 4 # 0xffffff8f + uint32_t pad1 : 1; + uint32_t gain_ctrl9_gc_rbb1 : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad2 : 2; + uint32_t gain_ctrl9_gc_rbb2 : 3; // @ 14 -- 12 # 0xffff8fff + uint32_t pad3 : 1; + uint32_t gain_ctrl10_gc_rbb1 : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad4 : 2; + uint32_t gain_ctrl10_gc_rbb2 : 3; // @ 22 -- 20 # 0xff8fffff + uint32_t pad5 : 1; + uint32_t gain_ctrl11_gc_rbb1 : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t pad6 : 2; + uint32_t gain_ctrl11_gc_rbb2 : 3; // @ 30 -- 28 # 0x8fffffff + uint32_t pad7 : 1; + }; + } rbb_gain_index3; // @ 0x10c + union { + uint32_t value; + struct { + uint32_t gain_ctrl12_gc_rbb1 : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 2; + uint32_t gain_ctrl12_gc_rbb2 : 3; // @ 6 -- 4 # 0xffffff8f + uint32_t pad1 : 1; + uint32_t gain_ctrl13_gc_rbb1 : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad2 : 2; + uint32_t gain_ctrl13_gc_rbb2 : 3; // @ 14 -- 12 # 0xffff8fff + uint32_t pad3 : 1; + uint32_t gain_ctrl14_gc_rbb1 : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad4 : 2; + uint32_t gain_ctrl14_gc_rbb2 : 3; // @ 22 -- 20 # 0xff8fffff + uint32_t pad5 : 1; + uint32_t gain_ctrl15_gc_rbb1 : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t pad6 : 2; + uint32_t gain_ctrl15_gc_rbb2 : 3; // @ 30 -- 28 # 0x8fffffff + uint32_t pad7 : 1; + }; + } rbb_gain_index4; // @ 0x110 + union { + uint32_t value; + struct { + uint32_t gain_ctrl16_gc_rbb1 : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 2; + uint32_t gain_ctrl16_gc_rbb2 : 3; // @ 6 -- 4 # 0xffffff8f + uint32_t pad1 : 25; + }; + } rbb_gain_index5; // @ 0x114 + union { + uint32_t value; + struct { + uint32_t gain_ctrl0_gc_tbb : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t pad0 : 3; + uint32_t gain_ctrl0_gc_tmx : 3; // @ 10 -- 8 # 0xfffff8ff + uint32_t pad1 : 1; + uint32_t gain_ctrl0_dac_bias_sel : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t gain_ctrl0_gc_tbb_boost : 2; // @ 15 -- 14 # 0xffff3fff + uint32_t gain_ctrl1_gc_tbb : 5; // @ 20 -- 16 # 0xffe0ffff + uint32_t pad2 : 3; + uint32_t gain_ctrl1_gc_tmx : 3; // @ 26 -- 24 # 0xf8ffffff + uint32_t pad3 : 1; + uint32_t gain_ctrl1_dac_bias_sel : 2; // @ 29 -- 28 # 0xcfffffff + uint32_t gain_ctrl1_gc_tbb_boost : 2; // @ 31 -- 30 # 0x3fffffff + }; + } tbb_gain_index1; // @ 0x118 + union { + uint32_t value; + struct { + uint32_t gain_ctrl2_gc_tbb : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t pad0 : 3; + uint32_t gain_ctrl2_gc_tmx : 3; // @ 10 -- 8 # 0xfffff8ff + uint32_t pad1 : 1; + uint32_t gain_ctrl2_dac_bias_sel : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t gain_ctrl2_gc_tbb_boost : 2; // @ 15 -- 14 # 0xffff3fff + uint32_t gain_ctrl3_gc_tbb : 5; // @ 20 -- 16 # 0xffe0ffff + uint32_t pad2 : 3; + uint32_t gain_ctrl3_gc_tmx : 3; // @ 26 -- 24 # 0xf8ffffff + uint32_t pad3 : 1; + uint32_t gain_ctrl3_dac_bias_sel : 2; // @ 29 -- 28 # 0xcfffffff + uint32_t gain_ctrl3_gc_tbb_boost : 2; // @ 31 -- 30 # 0x3fffffff + }; + } tbb_gain_index2; // @ 0x11c + union { + uint32_t value; + struct { + uint32_t gain_ctrl4_gc_tbb : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t pad0 : 3; + uint32_t gain_ctrl4_gc_tmx : 3; // @ 10 -- 8 # 0xfffff8ff + uint32_t pad1 : 1; + uint32_t gain_ctrl4_dac_bias_sel : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t gain_ctrl4_gc_tbb_boost : 2; // @ 15 -- 14 # 0xffff3fff + uint32_t gain_ctrl5_gc_tbb : 5; // @ 20 -- 16 # 0xffe0ffff + uint32_t pad2 : 3; + uint32_t gain_ctrl5_gc_tmx : 3; // @ 26 -- 24 # 0xf8ffffff + uint32_t pad3 : 1; + uint32_t gain_ctrl5_dac_bias_sel : 2; // @ 29 -- 28 # 0xcfffffff + uint32_t gain_ctrl5_gc_tbb_boost : 2; // @ 31 -- 30 # 0x3fffffff + }; + } tbb_gain_index3; // @ 0x120 + union { + uint32_t value; + struct { + uint32_t gain_ctrl6_gc_tbb : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t pad0 : 3; + uint32_t gain_ctrl6_gc_tmx : 3; // @ 10 -- 8 # 0xfffff8ff + uint32_t pad1 : 1; + uint32_t gain_ctrl6_dac_bias_sel : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t gain_ctrl6_gc_tbb_boost : 2; // @ 15 -- 14 # 0xffff3fff + uint32_t gain_ctrl7_gc_tbb : 5; // @ 20 -- 16 # 0xffe0ffff + uint32_t pad2 : 3; + uint32_t gain_ctrl7_gc_tmx : 3; // @ 26 -- 24 # 0xf8ffffff + uint32_t pad3 : 1; + uint32_t gain_ctrl7_dac_bias_sel : 2; // @ 29 -- 28 # 0xcfffffff + uint32_t gain_ctrl7_gc_tbb_boost : 2; // @ 31 -- 30 # 0x3fffffff + }; + } tbb_gain_index4; // @ 0x124 + union { + uint32_t value; + struct { + uint32_t pad0 : 12; + uint32_t pa_iet_11n : 4; // @ 15 -- 12 # 0xffff0fff + uint32_t pa_vbcore_11n : 4; // @ 19 -- 16 # 0xfff0ffff + uint32_t pa_vbcas_11n : 3; // @ 22 -- 20 # 0xff8fffff + uint32_t pad1 : 9; + }; + } pa_reg_ctrl_hw1; // @ 0x128 + union { + uint32_t value; + struct { + uint32_t pa_iet_11g : 4; // @ 3 -- 0 # 0xfffffff0 + uint32_t pa_vbcore_11g : 4; // @ 7 -- 4 # 0xffffff0f + uint32_t pa_vbcas_11g : 3; // @ 10 -- 8 # 0xfffff8ff + uint32_t pad0 : 1; + uint32_t pa_iet_11b : 4; // @ 15 -- 12 # 0xffff0fff + uint32_t pa_vbcore_11b : 4; // @ 19 -- 16 # 0xfff0ffff + uint32_t pa_vbcas_11b : 3; // @ 22 -- 20 # 0xff8fffff + uint32_t pad1 : 9; + }; + } pa_reg_ctrl_hw2; // @ 0x12c + union { + uint32_t value; + struct { + uint32_t pa_half_on_wifi : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 7; + uint32_t pa_etb_en_wifi : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pad1 : 7; + uint32_t pa_ib_fix_wifi : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad2 : 15; + }; + } pa_reg_wifi_ctrl_hw; // @ 0x130 + union { + uint32_t value; + struct { + uint32_t adda_ldo_dvdd_sel_rx : 3; // @ 2 -- 0 # 0xfffffff8 + uint32_t pad0 : 1; + uint32_t adda_ldo_dvdd_sel_tx : 3; // @ 6 -- 4 # 0xffffff8f + uint32_t pad1 : 25; + }; + } adda_reg_ctrl_hw; // @ 0x134 + union { + uint32_t value; + struct { + uint32_t lo_fbdv_halfstep_en_rx : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t lo_fbdv_halfstep_en_tx : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t lo_cp_sel_rx : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t lo_cp_sel_tx : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t lo_lf_cz_rx : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t pad0 : 2; + uint32_t lo_lf_cz_tx : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad1 : 2; + uint32_t lo_lf_rz_rx : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t pad2 : 2; + uint32_t lo_lf_rz_tx : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad3 : 2; + uint32_t lo_lf_r4_rx : 2; // @ 21 -- 20 # 0xffcfffff + uint32_t pad4 : 2; + uint32_t lo_lf_r4_tx : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t pad5 : 6; + }; + } lo_reg_ctrl_hw1; // @ 0x138 + union { + uint32_t value; + struct { + uint32_t lo_vco_idac_cw_2404 : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t pad0 : 3; + uint32_t lo_vco_freq_cw_2404 : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t lo_vco_idac_cw_2408 : 5; // @ 20 -- 16 # 0xffe0ffff + uint32_t pad1 : 3; + uint32_t lo_vco_freq_cw_2408 : 8; // @ 31 -- 24 # 0xffffff + }; + } lo_cal_ctrl_hw1; // @ 0x13c + union { + uint32_t value; + struct { + uint32_t lo_vco_idac_cw_2412 : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t pad0 : 3; + uint32_t lo_vco_freq_cw_2412 : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t lo_vco_idac_cw_2416 : 5; // @ 20 -- 16 # 0xffe0ffff + uint32_t pad1 : 3; + uint32_t lo_vco_freq_cw_2416 : 8; // @ 31 -- 24 # 0xffffff + }; + } lo_cal_ctrl_hw2; // @ 0x140 + union { + uint32_t value; + struct { + uint32_t lo_vco_idac_cw_2420 : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t pad0 : 3; + uint32_t lo_vco_freq_cw_2420 : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t lo_vco_idac_cw_2424 : 5; // @ 20 -- 16 # 0xffe0ffff + uint32_t pad1 : 3; + uint32_t lo_vco_freq_cw_2424 : 8; // @ 31 -- 24 # 0xffffff + }; + } lo_cal_ctrl_hw3; // @ 0x144 + union { + uint32_t value; + struct { + uint32_t lo_vco_idac_cw_2428 : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t pad0 : 3; + uint32_t lo_vco_freq_cw_2428 : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t lo_vco_idac_cw_2432 : 5; // @ 20 -- 16 # 0xffe0ffff + uint32_t pad1 : 3; + uint32_t lo_vco_freq_cw_2432 : 8; // @ 31 -- 24 # 0xffffff + }; + } lo_cal_ctrl_hw4; // @ 0x148 + union { + uint32_t value; + struct { + uint32_t lo_vco_idac_cw_2436 : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t pad0 : 3; + uint32_t lo_vco_freq_cw_2436 : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t lo_vco_idac_cw_2440 : 5; // @ 20 -- 16 # 0xffe0ffff + uint32_t pad1 : 3; + uint32_t lo_vco_freq_cw_2440 : 8; // @ 31 -- 24 # 0xffffff + }; + } lo_cal_ctrl_hw5; // @ 0x14c + union { + uint32_t value; + struct { + uint32_t lo_vco_idac_cw_2444 : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t pad0 : 3; + uint32_t lo_vco_freq_cw_2444 : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t lo_vco_idac_cw_2448 : 5; // @ 20 -- 16 # 0xffe0ffff + uint32_t pad1 : 3; + uint32_t lo_vco_freq_cw_2448 : 8; // @ 31 -- 24 # 0xffffff + }; + } lo_cal_ctrl_hw6; // @ 0x150 + union { + uint32_t value; + struct { + uint32_t lo_vco_idac_cw_2452 : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t pad0 : 3; + uint32_t lo_vco_freq_cw_2452 : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t lo_vco_idac_cw_2456 : 5; // @ 20 -- 16 # 0xffe0ffff + uint32_t pad1 : 3; + uint32_t lo_vco_freq_cw_2456 : 8; // @ 31 -- 24 # 0xffffff + }; + } lo_cal_ctrl_hw7; // @ 0x154 + union { + uint32_t value; + struct { + uint32_t lo_vco_idac_cw_2460 : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t pad0 : 3; + uint32_t lo_vco_freq_cw_2460 : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t lo_vco_idac_cw_2464 : 5; // @ 20 -- 16 # 0xffe0ffff + uint32_t pad1 : 3; + uint32_t lo_vco_freq_cw_2464 : 8; // @ 31 -- 24 # 0xffffff + }; + } lo_cal_ctrl_hw8; // @ 0x158 + union { + uint32_t value; + struct { + uint32_t lo_vco_idac_cw_2468 : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t pad0 : 3; + uint32_t lo_vco_freq_cw_2468 : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t lo_vco_idac_cw_2472 : 5; // @ 20 -- 16 # 0xffe0ffff + uint32_t pad1 : 3; + uint32_t lo_vco_freq_cw_2472 : 8; // @ 31 -- 24 # 0xffffff + }; + } lo_cal_ctrl_hw9; // @ 0x15c + union { + uint32_t value; + struct { + uint32_t lo_vco_idac_cw_2476 : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t pad0 : 3; + uint32_t lo_vco_freq_cw_2476 : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t lo_vco_idac_cw_2480 : 5; // @ 20 -- 16 # 0xffe0ffff + uint32_t pad1 : 3; + uint32_t lo_vco_freq_cw_2480 : 8; // @ 31 -- 24 # 0xffffff + }; + } lo_cal_ctrl_hw10; // @ 0x160 + union { + uint32_t value; + struct { + uint32_t lo_vco_idac_cw_2484 : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t pad0 : 3; + uint32_t lo_vco_freq_cw_2484 : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t pad1 : 16; + }; + } lo_cal_ctrl_hw11; // @ 0x164 + union { + uint32_t value; + struct { + uint32_t rosdac_i_gc0 : 6; // @ 5 -- 0 # 0xffffffc0 + uint32_t pad0 : 2; + uint32_t rosdac_q_gc0 : 6; // @ 13 -- 8 # 0xffffc0ff + uint32_t pad1 : 2; + uint32_t rosdac_i_gc1 : 6; // @ 21 -- 16 # 0xffc0ffff + uint32_t pad2 : 2; + uint32_t rosdac_q_gc1 : 6; // @ 29 -- 24 # 0xc0ffffff + uint32_t pad3 : 2; + }; + } rosdac_ctrl_hw1; // @ 0x168 + union { + uint32_t value; + struct { + uint32_t rosdac_i_gc2 : 6; // @ 5 -- 0 # 0xffffffc0 + uint32_t pad0 : 2; + uint32_t rosdac_q_gc2 : 6; // @ 13 -- 8 # 0xffffc0ff + uint32_t pad1 : 2; + uint32_t rosdac_i_gc3 : 6; // @ 21 -- 16 # 0xffc0ffff + uint32_t pad2 : 2; + uint32_t rosdac_q_gc3 : 6; // @ 29 -- 24 # 0xc0ffffff + uint32_t pad3 : 2; + }; + } rosdac_ctrl_hw2; // @ 0x16c + union { + uint32_t value; + struct { + uint32_t rx_iq_phase_comp_gc0 : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t pad0 : 6; + uint32_t rx_iq_gain_comp_gc0 : 11; // @ 26 -- 16 # 0xf800ffff + uint32_t pad1 : 5; + }; + } rxiq_ctrl_hw1; // @ 0x170 + union { + uint32_t value; + struct { + uint32_t rx_iq_phase_comp_gc1 : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t pad0 : 6; + uint32_t rx_iq_gain_comp_gc1 : 11; // @ 26 -- 16 # 0xf800ffff + uint32_t pad1 : 5; + }; + } rxiq_ctrl_hw2; // @ 0x174 + union { + uint32_t value; + struct { + uint32_t rx_iq_phase_comp_gc2 : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t pad0 : 6; + uint32_t rx_iq_gain_comp_gc2 : 11; // @ 26 -- 16 # 0xf800ffff + uint32_t pad1 : 5; + }; + } rxiq_ctrl_hw3; // @ 0x178 + union { + uint32_t value; + struct { + uint32_t rx_iq_phase_comp_gc3 : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t pad0 : 6; + uint32_t rx_iq_gain_comp_gc3 : 11; // @ 26 -- 16 # 0xf800ffff + uint32_t pad1 : 5; + }; + } rxiq_ctrl_hw4; // @ 0x17c + union { + uint32_t value; + struct { + uint32_t tbb_tosdac_i_gc0 : 6; // @ 5 -- 0 # 0xffffffc0 + uint32_t pad0 : 2; + uint32_t tbb_tosdac_q_gc0 : 6; // @ 13 -- 8 # 0xffffc0ff + uint32_t pad1 : 2; + uint32_t tbb_tosdac_i_gc1 : 6; // @ 21 -- 16 # 0xffc0ffff + uint32_t pad2 : 2; + uint32_t tbb_tosdac_q_gc1 : 6; // @ 29 -- 24 # 0xc0ffffff + uint32_t pad3 : 2; + }; + } tosdac_ctrl_hw1; // @ 0x180 + union { + uint32_t value; + struct { + uint32_t tbb_tosdac_i_gc2 : 6; // @ 5 -- 0 # 0xffffffc0 + uint32_t pad0 : 2; + uint32_t tbb_tosdac_q_gc2 : 6; // @ 13 -- 8 # 0xffffc0ff + uint32_t pad1 : 2; + uint32_t tbb_tosdac_i_gc3 : 6; // @ 21 -- 16 # 0xffc0ffff + uint32_t pad2 : 2; + uint32_t tbb_tosdac_q_gc3 : 6; // @ 29 -- 24 # 0xc0ffffff + uint32_t pad3 : 2; + }; + } tosdac_ctrl_hw2; // @ 0x184 + union { + uint32_t value; + struct { + uint32_t tbb_tosdac_i_gc4 : 6; // @ 5 -- 0 # 0xffffffc0 + uint32_t pad0 : 2; + uint32_t tbb_tosdac_q_gc4 : 6; // @ 13 -- 8 # 0xffffc0ff + uint32_t pad1 : 2; + uint32_t tbb_tosdac_i_gc5 : 6; // @ 21 -- 16 # 0xffc0ffff + uint32_t pad2 : 2; + uint32_t tbb_tosdac_q_gc5 : 6; // @ 29 -- 24 # 0xc0ffffff + uint32_t pad3 : 2; + }; + } tosdac_ctrl_hw3; // @ 0x188 + union { + uint32_t value; + struct { + uint32_t tbb_tosdac_i_gc6 : 6; // @ 5 -- 0 # 0xffffffc0 + uint32_t pad0 : 2; + uint32_t tbb_tosdac_q_gc6 : 6; // @ 13 -- 8 # 0xffffc0ff + uint32_t pad1 : 2; + uint32_t tbb_tosdac_i_gc7 : 6; // @ 21 -- 16 # 0xffc0ffff + uint32_t pad2 : 2; + uint32_t tbb_tosdac_q_gc7 : 6; // @ 29 -- 24 # 0xc0ffffff + uint32_t pad3 : 2; + }; + } tosdac_ctrl_hw4; // @ 0x18c + union { + uint32_t value; + struct { + uint32_t tx_iq_phase_comp_gc0 : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t pad0 : 6; + uint32_t tx_iq_gain_comp_gc0 : 11; // @ 26 -- 16 # 0xf800ffff + uint32_t pad1 : 5; + }; + } tx_iq_gain_hw0; // @ 0x190 + union { + uint32_t value; + struct { + uint32_t tx_iq_phase_comp_gc1 : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t pad0 : 6; + uint32_t tx_iq_gain_comp_gc1 : 11; // @ 26 -- 16 # 0xf800ffff + uint32_t pad1 : 5; + }; + } tx_iq_gain_hw1; // @ 0x194 + union { + uint32_t value; + struct { + uint32_t tx_iq_phase_comp_gc2 : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t pad0 : 6; + uint32_t tx_iq_gain_comp_gc2 : 11; // @ 26 -- 16 # 0xf800ffff + uint32_t pad1 : 5; + }; + } tx_iq_gain_hw2; // @ 0x198 + union { + uint32_t value; + struct { + uint32_t tx_iq_phase_comp_gc3 : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t pad0 : 6; + uint32_t tx_iq_gain_comp_gc3 : 11; // @ 26 -- 16 # 0xf800ffff + uint32_t pad1 : 5; + }; + } tx_iq_gain_hw3; // @ 0x19c + union { + uint32_t value; + struct { + uint32_t tx_iq_phase_comp_gc4 : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t pad0 : 6; + uint32_t tx_iq_gain_comp_gc4 : 11; // @ 26 -- 16 # 0xf800ffff + uint32_t pad1 : 5; + }; + } tx_iq_gain_hw4; // @ 0x1a0 + union { + uint32_t value; + struct { + uint32_t tx_iq_phase_comp_gc5 : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t pad0 : 6; + uint32_t tx_iq_gain_comp_gc5 : 11; // @ 26 -- 16 # 0xf800ffff + uint32_t pad1 : 5; + }; + } tx_iq_gain_hw5; // @ 0x1a4 + union { + uint32_t value; + struct { + uint32_t tx_iq_phase_comp_gc6 : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t pad0 : 6; + uint32_t tx_iq_gain_comp_gc6 : 11; // @ 26 -- 16 # 0xf800ffff + uint32_t pad1 : 5; + }; + } tx_iq_gain_hw6; // @ 0x1a8 + union { + uint32_t value; + struct { + uint32_t tx_iq_phase_comp_gc7 : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t pad0 : 6; + uint32_t tx_iq_gain_comp_gc7 : 11; // @ 26 -- 16 # 0xf800ffff + uint32_t pad1 : 5; + }; + } tx_iq_gain_hw7; // @ 0x1ac + union { + uint32_t value; + struct { + uint32_t lo_sdm_dither_sel_wlan_2412 : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t lo_sdm_dither_sel_wlan_2417 : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t lo_sdm_dither_sel_wlan_2422 : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t lo_sdm_dither_sel_wlan_2427 : 2; // @ 7 -- 6 # 0xffffff3f + uint32_t lo_sdm_dither_sel_wlan_2432 : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t lo_sdm_dither_sel_wlan_2437 : 2; // @ 11 -- 10 # 0xfffff3ff + uint32_t lo_sdm_dither_sel_wlan_2442 : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t lo_sdm_dither_sel_wlan_2447 : 2; // @ 15 -- 14 # 0xffff3fff + uint32_t lo_sdm_dither_sel_wlan_2452 : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t lo_sdm_dither_sel_wlan_2457 : 2; // @ 19 -- 18 # 0xfff3ffff + uint32_t lo_sdm_dither_sel_wlan_2462 : 2; // @ 21 -- 20 # 0xffcfffff + uint32_t lo_sdm_dither_sel_wlan_2467 : 2; // @ 23 -- 22 # 0xff3fffff + uint32_t lo_sdm_dither_sel_wlan_2472 : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t lo_sdm_dither_sel_wlan_2484 : 2; // @ 27 -- 26 # 0xf3ffffff + uint32_t pad0 : 4; + }; + } lo_sdm_ctrl_hw1; // @ 0x1b0 + union { + uint32_t value; + struct { + uint32_t lo_sdm_dither_sel_ble_2402 : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t lo_sdm_dither_sel_ble_2404 : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t lo_sdm_dither_sel_ble_2406 : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t lo_sdm_dither_sel_ble_2408 : 2; // @ 7 -- 6 # 0xffffff3f + uint32_t lo_sdm_dither_sel_ble_2410 : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t lo_sdm_dither_sel_ble_2412 : 2; // @ 11 -- 10 # 0xfffff3ff + uint32_t lo_sdm_dither_sel_ble_2414 : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t lo_sdm_dither_sel_ble_2416 : 2; // @ 15 -- 14 # 0xffff3fff + uint32_t lo_sdm_dither_sel_ble_2418 : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t lo_sdm_dither_sel_ble_2420 : 2; // @ 19 -- 18 # 0xfff3ffff + uint32_t lo_sdm_dither_sel_ble_2422 : 2; // @ 21 -- 20 # 0xffcfffff + uint32_t lo_sdm_dither_sel_ble_2424 : 2; // @ 23 -- 22 # 0xff3fffff + uint32_t lo_sdm_dither_sel_ble_2426 : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t lo_sdm_dither_sel_ble_2428 : 2; // @ 27 -- 26 # 0xf3ffffff + uint32_t lo_sdm_dither_sel_ble_2430 : 2; // @ 29 -- 28 # 0xcfffffff + uint32_t lo_sdm_dither_sel_ble_2432 : 2; // @ 31 -- 30 # 0x3fffffff + }; + } lo_sdm_ctrl_hw2; // @ 0x1b4 + union { + uint32_t value; + struct { + uint32_t lo_sdm_dither_sel_ble_2434 : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t lo_sdm_dither_sel_ble_2436 : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t lo_sdm_dither_sel_ble_2438 : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t lo_sdm_dither_sel_ble_2440 : 2; // @ 7 -- 6 # 0xffffff3f + uint32_t lo_sdm_dither_sel_ble_2442 : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t lo_sdm_dither_sel_ble_2444 : 2; // @ 11 -- 10 # 0xfffff3ff + uint32_t lo_sdm_dither_sel_ble_2446 : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t lo_sdm_dither_sel_ble_2448 : 2; // @ 15 -- 14 # 0xffff3fff + uint32_t lo_sdm_dither_sel_ble_2450 : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t lo_sdm_dither_sel_ble_2452 : 2; // @ 19 -- 18 # 0xfff3ffff + uint32_t lo_sdm_dither_sel_ble_2454 : 2; // @ 21 -- 20 # 0xffcfffff + uint32_t lo_sdm_dither_sel_ble_2456 : 2; // @ 23 -- 22 # 0xff3fffff + uint32_t lo_sdm_dither_sel_ble_2458 : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t lo_sdm_dither_sel_ble_2460 : 2; // @ 27 -- 26 # 0xf3ffffff + uint32_t lo_sdm_dither_sel_ble_2462 : 2; // @ 29 -- 28 # 0xcfffffff + uint32_t lo_sdm_dither_sel_ble_2464 : 2; // @ 31 -- 30 # 0x3fffffff + }; + } lo_sdm_ctrl_hw3; // @ 0x1b8 + union { + uint32_t value; + struct { + uint32_t lo_sdm_dither_sel_ble_2466 : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t lo_sdm_dither_sel_ble_2468 : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t lo_sdm_dither_sel_ble_2470 : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t lo_sdm_dither_sel_ble_2472 : 2; // @ 7 -- 6 # 0xffffff3f + uint32_t lo_sdm_dither_sel_ble_2474 : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t lo_sdm_dither_sel_ble_2476 : 2; // @ 11 -- 10 # 0xfffff3ff + uint32_t lo_sdm_dither_sel_ble_2478 : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t lo_sdm_dither_sel_ble_2480 : 2; // @ 15 -- 14 # 0xffff3fff + uint32_t lo_sdm_dither_sel_ble_tx : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad0 : 14; + }; + } lo_sdm_ctrl_hw4; // @ 0x1bc + union { + uint32_t value; + struct { + uint32_t lo_center_freq_mhz : 12; // @ 11 -- 0 # 0xfffff000 + uint32_t lo_sdm_bypass_mode : 6; // @ 17 -- 12 # 0xfffc0fff + uint32_t pad0 : 14; + }; + } lo_sdm_ctrl_hw5; // @ 0x1c0 + union { + uint32_t value; + struct { + uint32_t lo_sdmin_center : 29; // @ 28 -- 0 # 0xe0000000 + uint32_t pad0 : 3; + }; + } lo_sdm_ctrl_hw6; // @ 0x1c4 + union { + uint32_t value; + struct { + uint32_t lo_sdmin_1m : 20; // @ 19 -- 0 # 0xfff00000 + uint32_t pad0 : 12; + }; + } lo_sdm_ctrl_hw7; // @ 0x1c8 + union { + uint32_t value; + struct { + uint32_t lo_sdmin_if : 20; // @ 19 -- 0 # 0xfff00000 + uint32_t pad0 : 12; + }; + } lo_sdm_ctrl_hw8; // @ 0x1cc + union { + uint32_t value; + struct { + uint32_t rbb_bt_mode_ble : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 31; + }; + } rbb_bw_ctrl_hw; // @ 0x1d0 + uint8_t pad2[0x38]; + union { + uint32_t value; + struct { + uint32_t singen_inc_step1 : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t pad0 : 6; + uint32_t singen_inc_step0 : 10; // @ 25 -- 16 # 0xfc00ffff + uint32_t pad1 : 2; + uint32_t singen_unsign_en : 1; // @ 28 -- 28 # 0xefffffff + uint32_t singen_clkdiv_n : 2; // @ 30 -- 29 # 0x9fffffff + uint32_t singen_en : 1; // @ 31 -- 31 # 0x7fffffff + }; + } singen_ctrl0; // @ 0x20c + union { + uint32_t value; + struct { + uint32_t singen_clkdiv_q : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t pad0 : 2; + uint32_t singen_mode_q : 4; // @ 15 -- 12 # 0xffff0fff + uint32_t singen_clkdiv_i : 10; // @ 25 -- 16 # 0xfc00ffff + uint32_t pad1 : 2; + uint32_t singen_mode_i : 4; // @ 31 -- 28 # 0xfffffff + }; + } singen_ctrl1; // @ 0x210 + union { + uint32_t value; + struct { + uint32_t singen_gain_i : 11; // @ 10 -- 0 # 0xfffff800 + uint32_t pad0 : 1; + uint32_t singen_start_addr1_i : 10; // @ 21 -- 12 # 0xffc00fff + uint32_t singen_start_addr0_i : 10; // @ 31 -- 22 # 0x3fffff + }; + } singen_ctrl2; // @ 0x214 + union { + uint32_t value; + struct { + uint32_t singen_gain_q : 11; // @ 10 -- 0 # 0xfffff800 + uint32_t pad0 : 1; + uint32_t singen_start_addr1_q : 10; // @ 21 -- 12 # 0xffc00fff + uint32_t singen_start_addr0_q : 10; // @ 31 -- 22 # 0x3fffff + }; + } singen_ctrl3; // @ 0x218 + union { + uint32_t value; + struct { + uint32_t singen_fix_q : 12; // @ 11 -- 0 # 0xfffff000 + uint32_t singen_fix_en_q : 1; // @ 12 -- 12 # 0xffffefff + uint32_t pad0 : 3; + uint32_t singen_fix_i : 12; // @ 27 -- 16 # 0xf000ffff + uint32_t singen_fix_en_i : 1; // @ 28 -- 28 # 0xefffffff + uint32_t pad1 : 3; + }; + } singen_ctrl4; // @ 0x21c + union { + uint32_t value; + struct { + uint32_t rfckg_rxclk_4s_on : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t rfckg_txclk_4s_on : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t rfckg_adc_afifo_inv : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t rfckg_adc_clkout_sel : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t rfckg_dac_afifo_inv : 1; // @ 4 -- 4 # 0xffffffef + uint32_t rx_dfe_en_4s : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t rx_dfe_en_4s_en : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t tx_dfe_en_4s : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t tx_dfe_en_4s_en : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t rx_test_sel : 2; // @ 10 -- 9 # 0xfffff9ff + uint32_t tx_test_sel : 2; // @ 12 -- 11 # 0xffffe7ff + uint32_t pad_adc_clkout_inv_en : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t pad_dac_clkout_inv_en : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t rf_ch_ind_ble_4s : 7; // @ 21 -- 15 # 0xffc07fff + uint32_t rf_ch_ind_ble_4s_en : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t wifimode_4s : 2; // @ 24 -- 23 # 0xfe7fffff + uint32_t wifimode_4s_en : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t bbmode_4s : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t bbmode_4s_en : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t test_sel : 4; // @ 31 -- 28 # 0xfffffff + }; + } rfif_dfe_ctrl0; // @ 0x220 + union { + uint32_t value; + struct { + uint32_t test_read : 32; // @ 31 -- 0 # 0x0 + }; + } rfif_test_read; // @ 0x224 + union { + uint32_t value; + struct { + uint32_t test_from_pad_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t test_gc_from_pad_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t rfckg_rxclk_div2_mode : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t rfif_int_lo_unlocked_mask : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pad0 : 12; + uint32_t rfif_ppud_cnt2 : 9; // @ 24 -- 16 # 0xfe00ffff + uint32_t rfif_ppud_cnt1 : 5; // @ 29 -- 25 # 0xc1ffffff + uint32_t rfif_ppud_manaual_en : 1; // @ 30 -- 30 # 0xbfffffff + uint32_t pad1 : 1; + }; + } rfif_dig_ctrl; // @ 0x228 + union { + uint32_t value; + struct { + uint32_t rf_data_temp_0 : 32; // @ 31 -- 0 # 0x0 + }; + } rf_data_temp_0; // @ 0x22c + union { + uint32_t value; + struct { + uint32_t rf_data_temp_1 : 32; // @ 31 -- 0 # 0x0 + }; + } rf_data_temp_1; // @ 0x230 + union { + uint32_t value; + struct { + uint32_t rf_data_temp_2 : 32; // @ 31 -- 0 # 0x0 + }; + } rf_data_temp_2; // @ 0x234 + union { + uint32_t value; + struct { + uint32_t rf_data_temp_3 : 32; // @ 31 -- 0 # 0x0 + }; + } rf_data_temp_3; // @ 0x238 + union { + uint32_t value; + struct { + uint32_t rf_sram_link_dly : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t rf_sram_link_mode : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t rf_sram_swap : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t rf_sram_ext_clr : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t pad0 : 12; + }; + } rf_sram_ctrl0; // @ 0x23c + union { + uint32_t value; + struct { + uint32_t rf_sram_adc_done : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t rf_sram_adc_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t rf_sram_adc_loop_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t rf_sram_adc_sts_clr : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pad0 : 12; + uint32_t rf_sram_adc_done_cnt : 16; // @ 31 -- 16 # 0xffff + }; + } rf_sram_ctrl1; // @ 0x240 + union { + uint32_t value; + struct { + uint32_t rf_sram_adc_addr_end : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t rf_sram_adc_addr_start : 16; // @ 31 -- 16 # 0xffff + }; + } rf_sram_ctrl2; // @ 0x244 + union { + uint32_t value; + struct { + uint32_t rf_sram_adc_sts : 32; // @ 31 -- 0 # 0x0 + }; + } rf_sram_ctrl3; // @ 0x248 + union { + uint32_t value; + struct { + uint32_t rf_sram_dac_done : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t rf_sram_dac_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t rf_sram_dac_loop_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t rf_sram_dac_sts_clr : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pad0 : 12; + uint32_t rf_sram_dac_done_cnt : 16; // @ 31 -- 16 # 0xffff + }; + } rf_sram_ctrl4; // @ 0x24c + union { + uint32_t value; + struct { + uint32_t rf_sram_dac_addr_end : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t rf_sram_dac_addr_start : 16; // @ 31 -- 16 # 0xffff + }; + } rf_sram_ctrl5; // @ 0x250 + union { + uint32_t value; + struct { + uint32_t rf_sram_dac_sts : 32; // @ 31 -- 0 # 0x0 + }; + } rf_sram_ctrl6; // @ 0x254 + union { + uint32_t value; + struct { + uint32_t rf_ical_r_cnt_n : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t rf_ical_a_cnt_n : 10; // @ 19 -- 10 # 0xfff003ff + uint32_t rf_ical_f_cnt_n : 10; // @ 29 -- 20 # 0xc00fffff + uint32_t rf_ical_a_ud_inv_en : 1; // @ 30 -- 30 # 0xbfffffff + uint32_t rf_ical_f_ud_inv_en : 1; // @ 31 -- 31 # 0x7fffffff + }; + } rf_ical_ctrl0; // @ 0x258 + union { + uint32_t value; + struct { + uint32_t rf_ical_r_avg_n : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t pad0 : 5; + uint32_t rf_ical_r_os_q : 10; // @ 19 -- 10 # 0xfff003ff + uint32_t rf_ical_r_os_i : 10; // @ 29 -- 20 # 0xc00fffff + uint32_t pad1 : 2; + }; + } rf_ical_ctrl1; // @ 0x25c + union { + uint32_t value; + struct { + uint32_t rf_ical_period_n : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } rf_ical_ctrl2; // @ 0x260 + union { + uint32_t value; + struct { + uint32_t rf_ch_ind_wifi : 12; // @ 11 -- 0 # 0xfffff000 + uint32_t pad0 : 20; + }; + } rf_fsm_ctrl0; // @ 0x264 + union { + uint32_t value; + struct { + uint32_t rf_fsm_lo_time : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t rf_fsm_lo_rdy : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t rf_fsm_lo_rdy_rst : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t rf_fsm_lo_rdy_4s_1 : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t rf_fsm_lo_rdy_sbclr : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t rf_fsm_pu_pa_dly_n : 10; // @ 29 -- 20 # 0xc00fffff + uint32_t pad0 : 2; + }; + } rf_fsm_ctrl1; // @ 0x268 + union { + uint32_t value; + struct { + uint32_t rf_fsm_st_dbg : 3; // @ 2 -- 0 # 0xfffffff8 + uint32_t rf_fsm_st_dbg_en : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t rf_trx_en_ble_4s : 1; // @ 4 -- 4 # 0xffffffef + uint32_t rf_trx_sw_ble_4s : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t rf_trx_ble_4s_en : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t pad0 : 3; + uint32_t rf_fsm_dfe_tx_dly_n : 10; // @ 19 -- 10 # 0xfff003ff + uint32_t rf_fsm_dfe_rx_dly_n : 10; // @ 29 -- 20 # 0xc00fffff + uint32_t pad1 : 2; + }; + } rf_fsm_ctrl2; // @ 0x26c + union { + uint32_t value; + struct { + uint32_t pkdet_out_cnt_sts : 4; // @ 3 -- 0 # 0xfffffff0 + uint32_t pkdet_out_cnt_en : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pkdet_out_mode : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad0 : 26; + }; + } rf_pkdet_ctrl0; // @ 0x270 + uint8_t pad3[0x38c]; + union { + uint32_t value; + struct { + uint32_t tx_iqc_phase : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t tx_iqc_phase_en : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t pad0 : 1; + uint32_t tx_iqc_gain : 11; // @ 22 -- 12 # 0xff800fff + uint32_t tx_iqc_gain_en : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t tx_dvga_gain_qdb : 7; // @ 30 -- 24 # 0x80ffffff + uint32_t tx_dvga_gain_ctrl_hw : 1; // @ 31 -- 31 # 0x7fffffff + }; + } dfe_ctrl_0; // @ 0x600 + union { + uint32_t value; + struct { + uint32_t tx_dac_os_i : 12; // @ 11 -- 0 # 0xfffff000 + uint32_t pad0 : 4; + uint32_t tx_dac_os_q : 12; // @ 27 -- 16 # 0xf000ffff + uint32_t pad1 : 2; + uint32_t tx_dac_dat_format : 1; // @ 30 -- 30 # 0xbfffffff + uint32_t tx_dac_iq_swap : 1; // @ 31 -- 31 # 0x7fffffff + }; + } dfe_ctrl_1; // @ 0x604 + union { + uint32_t value; + struct { + uint32_t rx_adc_os_i : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t pad0 : 6; + uint32_t rx_adc_os_q : 10; // @ 25 -- 16 # 0xfc00ffff + uint32_t pad1 : 2; + uint32_t rx_adc_dce_flt_en : 1; // @ 28 -- 28 # 0xefffffff + uint32_t rx_adc_low_pow_en : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t rx_adc_dat_format : 1; // @ 30 -- 30 # 0xbfffffff + uint32_t rx_adc_iq_swap : 1; // @ 31 -- 31 # 0x7fffffff + }; + } dfe_ctrl_2; // @ 0x608 + union { + uint32_t value; + struct { + uint32_t rx_adc_4s_i_val : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t rx_adc_4s_i_en : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t pad0 : 5; + uint32_t rx_adc_4s_q_val : 10; // @ 25 -- 16 # 0xfc00ffff + uint32_t rx_adc_4s_q_en : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t pad1 : 5; + }; + } dfe_ctrl_3; // @ 0x60c + union { + uint32_t value; + struct { + uint32_t rx_pf_th2 : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t pad0 : 6; + uint32_t rx_pf_th1 : 10; // @ 25 -- 16 # 0xfc00ffff + uint32_t pad1 : 4; + uint32_t rx_pf_q_en : 1; // @ 30 -- 30 # 0xbfffffff + uint32_t rx_pf_i_en : 1; // @ 31 -- 31 # 0x7fffffff + }; + } dfe_ctrl_4; // @ 0x610 + union { + uint32_t value; + struct { + uint32_t rx_iqc_phase : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t rx_iqc_phase_en : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t pad0 : 1; + uint32_t rx_iqc_gain : 11; // @ 22 -- 12 # 0xff800fff + uint32_t rx_iqc_gain_en : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t pad1 : 8; + }; + } dfe_ctrl_5; // @ 0x614 + union { + uint32_t value; + struct { + uint32_t rx_pm_freqshift_cw : 20; // @ 19 -- 0 # 0xfff00000 + uint32_t rx_pm_freqshift_en : 1; // @ 20 -- 20 # 0xffefffff + uint32_t pad0 : 7; + uint32_t rx_pm_done : 1; // @ 28 -- 28 # 0xefffffff + uint32_t rx_pm_en : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t rx_pm_in_sel : 2; // @ 31 -- 30 # 0x3fffffff + }; + } dfe_ctrl_6; // @ 0x618 + union { + uint32_t value; + struct { + uint32_t rx_pm_start_ofs : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t rx_pm_acc_len : 16; // @ 31 -- 16 # 0xffff + }; + } dfe_ctrl_7; // @ 0x61c + union { + uint32_t value; + struct { + uint32_t rx_pm_iqacc_i : 25; // @ 24 -- 0 # 0xfe000000 + uint32_t pad0 : 7; + }; + } dfe_ctrl_8; // @ 0x620 + union { + uint32_t value; + struct { + uint32_t rx_pm_iqacc_q : 25; // @ 24 -- 0 # 0xfe000000 + uint32_t pad0 : 7; + }; + } dfe_ctrl_9; // @ 0x624 + union { + uint32_t value; + struct { + uint32_t dfe_dac_raw_i : 11; // @ 10 -- 0 # 0xfffff800 + uint32_t pad0 : 5; + uint32_t dfe_dac_raw_q : 11; // @ 26 -- 16 # 0xf800ffff + uint32_t pad1 : 5; + }; + } dfe_ctrl_10; // @ 0x628 + union { + uint32_t value; + struct { + uint32_t dfe_adc_raw_i : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t pad0 : 6; + uint32_t dfe_adc_raw_q : 10; // @ 25 -- 16 # 0xfc00ffff + uint32_t pad1 : 6; + }; + } dfe_ctrl_11; // @ 0x62c + union { + uint32_t value; + struct { + uint32_t tx_dvga_gain_qdb_gc0 : 7; // @ 6 -- 0 # 0xffffff80 + uint32_t pad0 : 1; + uint32_t tx_dvga_gain_qdb_gc1 : 7; // @ 14 -- 8 # 0xffff80ff + uint32_t pad1 : 1; + uint32_t tx_dvga_gain_qdb_gc2 : 7; // @ 22 -- 16 # 0xff80ffff + uint32_t pad2 : 1; + uint32_t tx_dvga_gain_qdb_gc3 : 7; // @ 30 -- 24 # 0x80ffffff + uint32_t pad3 : 1; + }; + } dfe_ctrl_12; // @ 0x630 + union { + uint32_t value; + struct { + uint32_t tx_dvga_gain_qdb_gc4 : 7; // @ 6 -- 0 # 0xffffff80 + uint32_t pad0 : 1; + uint32_t tx_dvga_gain_qdb_gc5 : 7; // @ 14 -- 8 # 0xffff80ff + uint32_t pad1 : 1; + uint32_t tx_dvga_gain_qdb_gc6 : 7; // @ 22 -- 16 # 0xff80ffff + uint32_t pad2 : 1; + uint32_t tx_dvga_gain_qdb_gc7 : 7; // @ 30 -- 24 # 0x80ffffff + uint32_t pad3 : 1; + }; + } dfe_ctrl_13; // @ 0x634 + union { + uint32_t value; + struct { + uint32_t tx_dvga_gain_qdb_gc8 : 7; // @ 6 -- 0 # 0xffffff80 + uint32_t pad0 : 1; + uint32_t tx_dvga_gain_qdb_gc9 : 7; // @ 14 -- 8 # 0xffff80ff + uint32_t pad1 : 1; + uint32_t tx_dvga_gain_qdb_gc10 : 7; // @ 22 -- 16 # 0xff80ffff + uint32_t pad2 : 1; + uint32_t tx_dvga_gain_qdb_gc11 : 7; // @ 30 -- 24 # 0x80ffffff + uint32_t pad3 : 1; + }; + } dfe_ctrl_14; // @ 0x638 + union { + uint32_t value; + struct { + uint32_t tx_dvga_gain_qdb_gc12 : 7; // @ 6 -- 0 # 0xffffff80 + uint32_t pad0 : 1; + uint32_t tx_dvga_gain_qdb_gc13 : 7; // @ 14 -- 8 # 0xffff80ff + uint32_t pad1 : 1; + uint32_t tx_dvga_gain_qdb_gc14 : 7; // @ 22 -- 16 # 0xff80ffff + uint32_t pad2 : 1; + uint32_t tx_dvga_gain_qdb_gc15 : 7; // @ 30 -- 24 # 0x80ffffff + uint32_t pad3 : 1; + }; + } dfe_ctrl_15; // @ 0x63c + union { + uint32_t value; + struct { + uint32_t rf_tbb_ind_gc0 : 3; // @ 2 -- 0 # 0xfffffff8 + uint32_t pad0 : 1; + uint32_t rf_tbb_ind_gc1 : 3; // @ 6 -- 4 # 0xffffff8f + uint32_t pad1 : 1; + uint32_t rf_tbb_ind_gc2 : 3; // @ 10 -- 8 # 0xfffff8ff + uint32_t pad2 : 1; + uint32_t rf_tbb_ind_gc3 : 3; // @ 14 -- 12 # 0xffff8fff + uint32_t pad3 : 1; + uint32_t rf_tbb_ind_gc4 : 3; // @ 18 -- 16 # 0xfff8ffff + uint32_t pad4 : 1; + uint32_t rf_tbb_ind_gc5 : 3; // @ 22 -- 20 # 0xff8fffff + uint32_t pad5 : 1; + uint32_t rf_tbb_ind_gc6 : 3; // @ 26 -- 24 # 0xf8ffffff + uint32_t pad6 : 1; + uint32_t rf_tbb_ind_gc7 : 3; // @ 30 -- 28 # 0x8fffffff + uint32_t pad7 : 1; + }; + } dfe_ctrl_16; // @ 0x640 + union { + uint32_t value; + struct { + uint32_t rf_tbb_ind_gc8 : 3; // @ 2 -- 0 # 0xfffffff8 + uint32_t pad0 : 1; + uint32_t rf_tbb_ind_gc9 : 3; // @ 6 -- 4 # 0xffffff8f + uint32_t pad1 : 1; + uint32_t rf_tbb_ind_gc10 : 3; // @ 10 -- 8 # 0xfffff8ff + uint32_t pad2 : 1; + uint32_t rf_tbb_ind_gc11 : 3; // @ 14 -- 12 # 0xffff8fff + uint32_t pad3 : 1; + uint32_t rf_tbb_ind_gc12 : 3; // @ 18 -- 16 # 0xfff8ffff + uint32_t pad4 : 1; + uint32_t rf_tbb_ind_gc13 : 3; // @ 22 -- 20 # 0xff8fffff + uint32_t pad5 : 1; + uint32_t rf_tbb_ind_gc14 : 3; // @ 26 -- 24 # 0xf8ffffff + uint32_t pad6 : 1; + uint32_t rf_tbb_ind_gc15 : 3; // @ 30 -- 28 # 0x8fffffff + uint32_t pad7 : 1; + }; + } dfe_ctrl_17; // @ 0x644 + union { + uint32_t value; + struct { + uint32_t tx_dvga_gain_qdb_ble_gc0 : 7; // @ 6 -- 0 # 0xffffff80 + uint32_t pad0 : 1; + uint32_t tx_dvga_gain_qdb_ble_gc1 : 7; // @ 14 -- 8 # 0xffff80ff + uint32_t pad1 : 1; + uint32_t tx_dvga_gain_qdb_ble_gc2 : 7; // @ 22 -- 16 # 0xff80ffff + uint32_t pad2 : 9; + }; + } dfe_ctrl_18; // @ 0x648 + }; +} rf_regs; +#define RF_BASE 0x40001000 +#define RF ((rf_regs* volatile)(RF_BASE)) \ No newline at end of file From b346a663b9a38d6e1c2ee2e3d423972b0184b4c6 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 25 Jul 2021 02:20:12 -0500 Subject: [PATCH 042/148] add rf_priv header --- src/bl602_wifi/bl602_rf_private.h | 81 +++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 src/bl602_wifi/bl602_rf_private.h diff --git a/src/bl602_wifi/bl602_rf_private.h b/src/bl602_wifi/bl602_rf_private.h new file mode 100644 index 0000000..bead91b --- /dev/null +++ b/src/bl602_wifi/bl602_rf_private.h @@ -0,0 +1,81 @@ +#ifndef _BL602_RF_PRIVATE_H_ +#define _BL602_RF_PRIVATE_H_ +#include + +struct anon_struct { + uint32_t index; + int32_t dvga; +}; + +typedef struct anon_struct anon_struct; + +struct anon_struct { + uint32_t vbcore; + uint32_t iet; + uint32_t vbcore_11n; + uint32_t iet_11n; + uint32_t vbcore_11g; + uint32_t iet_11g; + uint32_t vbcore_11b; + uint32_t iet_11b; + uint32_t lo_fbdv_halfstep_en; + uint32_t lo_fbdv_halfstep_en_tx; + uint32_t lo_fbdv_halfstep_en_rx; + uint32_t clkpll_reset_postdiv; + uint32_t clkpll_dither_sel; +}; + +struct notch_param { + uint32_t notch_en; + int32_t spur_freq; +}; + +typedef struct notch_param notch_param; + +struct regs_to_opti { + uint32_t vbcore; + uint32_t iet; + uint32_t vbcore_11n; + uint32_t iet_11n; + uint32_t vbcore_11g; + uint32_t iet_11g; + uint32_t vbcore_11b; + uint32_t iet_11b; + uint32_t lo_fbdv_halfstep_en; + uint32_t lo_fbdv_halfstep_en_tx; + uint32_t lo_fbdv_halfstep_en_rx; + uint32_t clkpll_reset_postdiv; + uint32_t clkpll_dither_sel; +}; + +typedef struct regs_to_opti regs_to_opti; + +struct tx_pwr_index { + uint32_t index; + int32_t dvga; +}; + +typedef struct tx_pwr_index tx_pwr_index; + +void rf_pri_config_bandwidth(uint32_t bw); +void rf_pri_fcal(void); +void rf_pri_full_cal(void); +void rf_pri_get_notch_param(uint32_t chanfreq_MHz, uint8_t * ncf_on, int32_t * ncf_freq_Hz); +uint32_t rf_pri_get_txgain_index(int32_t pwr, uint32_t mode); +int32_t rf_pri_get_txgain_max(void); +int32_t rf_pri_get_txgain_min(void); +uint32_t rf_pri_get_vco_freq_cw(uint32_t chanfreq_MHz); +uint32_t rf_pri_get_vco_idac_cw(uint32_t chanfreq_MHz); +void rf_pri_init(uint8_t reset, uint8_t chipv); +void rf_pri_init_fast(uint32_t flag); +void rf_pri_lo_acal(void); +void rf_pri_query_txgain_table(uint32_t index, uint32_t * rfg_index, uint32_t * dg); +void rf_pri_rccal(void); +void rf_pri_tx_gain_comp(int32_t Tsens); +void rf_pri_txcal(void); +void rf_pri_update_param(uint32_t chanfreq_MHz); +void rf_pri_update_power_offset(int32_t * power_offset); +void rf_pri_update_tx_power_offset(uint8_t channel, int8_t * power_offset); +void rf_pri_update_txgain_tempos(int16_t tempos); +void rf_pri_xtalfreq(uint32_t xtalfreq); +#endif \ No newline at end of file From 49a3fd6f770083d8faa0be149a38e5f4ceb43a02 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 25 Jul 2021 02:20:34 -0500 Subject: [PATCH 043/148] fix return true --- src/bl602_wifi/phy_hal.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bl602_wifi/phy_hal.c b/src/bl602_wifi/phy_hal.c index 2a7f6ca..3d44b30 100644 --- a/src/bl602_wifi/phy_hal.c +++ b/src/bl602_wifi/phy_hal.c @@ -35,6 +35,7 @@ void hal_get_capcode_asymm(uint8_t *capcode_in, uint8_t *capcode_out) { bool hal_get_temperature(int16_t *temperature) { *temperature = hal_env.temperature; + return 1; } void hal_set_temperature(int16_t temperature) { From 1106214d88b99551dad0b61c4362653ba9e03fb4 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 25 Jul 2021 02:20:48 -0500 Subject: [PATCH 044/148] add tcal --- src/bl602_wifi/phy_tcal.c | 62 +++++++++++++++++++++++++++++++++++++++ src/bl602_wifi/phy_tcal.h | 15 ++++++++++ 2 files changed, 77 insertions(+) create mode 100644 src/bl602_wifi/phy_tcal.c diff --git a/src/bl602_wifi/phy_tcal.c b/src/bl602_wifi/phy_tcal.c new file mode 100644 index 0000000..980727e --- /dev/null +++ b/src/bl602_wifi/phy_tcal.c @@ -0,0 +1,62 @@ +#include "phy_tcal.h" +#include "phy_hal.h" +#include "phy_bl602.h" +#include "phy_trpc.h" +#include "bl602_rf_private.h" + +static struct tcal_tag tcal_env; // :41:24 + +void phy_tcal_reset(void) { + memset(&tcal_env,0,0x38); + tcal_env.prev_temperature = 0x19; + tcal_env.last_action_temperature[0] = 0x19; + tcal_env.last_action_temperature[1] = 0x19; + tcal_env.last_action_temperature[2] = 0x19; + tcal_env.last_action_temperature[3] = 0x19; + tcal_env.enabled = 1; +} + +void phy_tcal_start(void) { + tcal_env.enabled = 1; +} + +void phy_tcal_stop(void) { + tcal_env.enabled = 0; +} + +void phy_tcal_handle(void) { + int16_t temp; + if (hal_get_temperature(&temp)) { + phy_tcal_txpwr(temp); + int cutoff = temp; + if (cutoff > 125) + cutoff = 125; + if (cutoff < -40) + cutoff = -40; + // iVar3 = (int)((uVar2 - 0x19) * 0x10000) >> 0x10; sign? + int offset = cutoff - 25; + if (offset < 1) { + offset = (offset * -6) >> 8; + } else { + offset = ((offset * 6) >> 8) * (-1); + } + if (offset != tcal_env.last_action_out[2]) { + phy_config_rxgain(offset); + tcal_env.last_action_temperature[2] = cutoff; + tcal_env.last_action_out[2] = offset; + } + tcal_env.prev_temperature = temp; + } +} + +void phy_tcal_callback(int16_t temperature) { + hal_set_temperature(temperature); + if (tcal_env.enabled) { + phy_tcal_handle(); + } +} + +void phy_tcal_txpwr(int16_t curr_temperature) { + rf_pri_tx_gain_comp(curr_temperature); + trpc_update_vs_temperature((int8_t)curr_temperature); +} diff --git a/src/bl602_wifi/phy_tcal.h b/src/bl602_wifi/phy_tcal.h index 87cb0c7..db84c03 100644 --- a/src/bl602_wifi/phy_tcal.h +++ b/src/bl602_wifi/phy_tcal.h @@ -1,6 +1,21 @@ #ifndef _PHY_TCAL_H_ #define _PHY_TCAL_H_ + +#include + void phy_tcal_reset(void); void phy_tcal_start(void); +struct tcal_tag { + int16_t prev_temperature; // +0 + uint32_t last_action_time[4]; // +4 + uint32_t last_action_temperature[4]; // +20 + int32_t last_action_out[4]; // +36 + bool enabled; // +52 +}; // :29:8 + +void phy_tcal_stop(void); // :69:6 +void phy_tcal_handle(void); // :74:6 +void phy_tcal_callback(int16_t temperature); // :104:6 +void phy_tcal_txpwr(int16_t curr_temperature); // :141:6 #endif \ No newline at end of file From 908848339941b1d934f0a40fdb6b9f0fbf4b2259 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 25 Jul 2021 02:20:57 -0500 Subject: [PATCH 045/148] add trpc --- src/bl602_wifi/phy_trpc.c | 111 ++++++++++++++++++++++++++++++++++++++ src/bl602_wifi/phy_trpc.h | 19 +++++++ 2 files changed, 130 insertions(+) create mode 100644 src/bl602_wifi/phy_trpc.c diff --git a/src/bl602_wifi/phy_trpc.c b/src/bl602_wifi/phy_trpc.c new file mode 100644 index 0000000..5ac8e0d --- /dev/null +++ b/src/bl602_wifi/phy_trpc.c @@ -0,0 +1,111 @@ +#include "phy_trpc.h" +#include "phy_bl602.h" +#include "bl602_rf_private.h" +#include "utils.h" + +static int8_t txpwr_vs_rate_table[3][8] = { + {0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12}, + {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, 0x0e}, + {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, 0x0e}, +}; // :12:15 + +static struct trpc_env_tag trpc_env; + +uint8_t trpc_get_default_power_idx(uint8_t formatmod, uint8_t mcs) { + if (formatmod > PHY_FORMATMOD_11N) { + formatmod = PHY_FORMATMOD_11N; + } + int mcs_max = 3; + if (formatmod) { + mcs_max = 7; + } + if (mcs > mcs_max) { + mcs = mcs_max; + } + return trpc_get_power_idx(formatmod, mcs, txpwr_vs_rate_table[formatmod][mcs]); +} + +uint8_t trpc_get_power_idx(uint8_t formatmod, uint8_t mcs, int8_t pwr_dbm) { + if (formatmod > PHY_FORMATMOD_11N) { + formatmod = PHY_FORMATMOD_11N; + } + int mcs_max = 3; + if (formatmod) { + mcs_max = 7; + } + if (mcs > mcs_max) { + mcs = mcs_max; + } + int pwr = MIN(trpc_env.power_dbm_max_rf, trpc_env.power_dbm_lim_reg); + pwr = MIN(pwr, pwr_dbm); + pwr = MIN(pwr, txpwr_vs_rate_table[formatmod][mcs]); + pwr = MAX(pwr, trpc_env.power_dbm_min_rf); + int x = (int)(((double)((int)(pwr * -510 + trpc_env.power_dbm_max_rf) / 512)) + (double)0.5) & 0xff; + int y = 3; + if (formatmod) { + y = 0; + } + x = (y + x) & 0xff; + if (x > 0xf) + x = 0xf; + return x << 2; +} + +int8_t trpc_get_rf_max_power() { + return trpc_env.power_dbm_max_rf; +} + +int8_t trpc_get_rf_min_power() { + return trpc_env.power_dbm_min_rf; +} + +void trpc_init(void) { + trpc_env.channel_freq = 2442; + trpc_env.power_dbm_max_rf = rf_pri_get_txgain_max(); + trpc_env.power_dbm_min_rf = rf_pri_get_txgain_min(); + trpc_env.power_dbm_lim_reg = 30; + trpc_env.temperature = 25; +} + +void trpc_power_get(int8_t *power_rate_table) { + memcpy(power_rate_table, txpwr_vs_rate_table, sizeof(txpwr_vs_rate_table)); +} + +void trpc_update_power(int8_t (*power_rate_table) [8]) { + for (int i = 0; i < 3; i ++) { + for (int j = 0; j < 8; j++) { + txpwr_vs_rate_table[i][j] = power_rate_table[i][j]; + } + } +} + +void trpc_update_power_11b(int8_t *power_rate_table) { + for (int j = 0; j < 8; j++) { + txpwr_vs_rate_table[0][j] = power_rate_table[j]; + } +} + +void trpc_update_power_11g(int8_t *power_rate_table) { + for (int j = 0; j < 8; j++) { + txpwr_vs_rate_table[1][j] = power_rate_table[j]; + } +} + +void trpc_update_power_11n(int8_t *power_rate_table) { + for (int j = 0; j < 8; j++) { + txpwr_vs_rate_table[2][j] = power_rate_table[j]; + } +} + +void trpc_update_vs_channel(int8_t channel_MHz) { + trpc_env.channel_freq = channel_MHz; + trpc_env.power_dbm_max_rf = rf_pri_get_txgain_max(); + trpc_env.power_dbm_min_rf = rf_pri_get_txgain_min(); +} + + +void trpc_update_vs_temperature(int8_t temperature) { + trpc_env.temperature = temperature; + trpc_env.power_dbm_max_rf = rf_pri_get_txgain_max(); + trpc_env.power_dbm_min_rf = rf_pri_get_txgain_min(); +} diff --git a/src/bl602_wifi/phy_trpc.h b/src/bl602_wifi/phy_trpc.h index e4480d9..4ea0a66 100644 --- a/src/bl602_wifi/phy_trpc.h +++ b/src/bl602_wifi/phy_trpc.h @@ -1,9 +1,28 @@ #ifndef _PHY_TRPC_H_ #define _PHY_TRPC_H_ #include + +struct trpc_env_tag { + int8_t power_dbm_max_rf; // +0 + int8_t power_dbm_min_rf; // +1 + int8_t power_dbm_lim_reg; // +2 + int16_t channel_freq; // +4 + int8_t temperature; // +6 + int8_t temperature_compensate; // +7 +}; + void trpc_init(void); int8_t trpc_get_rf_max_power(void); int8_t trpc_get_rf_min_power(void); uint8_t trpc_get_power_idx(uint8_t formatmod, uint8_t mcs, int8_t pwr_dbm); void trpc_update_vs_channel(int8_t channel_MHz); // :171:6 + +uint8_t trpc_get_default_power_idx(uint8_t formatmod,uint8_t mcs); +void trpc_power_get(int8_t * power_rate_table); +void trpc_update_power(int8_t (*power_rate_table) [8]); +void trpc_update_power_11b(int8_t * power_rate_table); +void trpc_update_power_11g(int8_t * power_rate_table); +void trpc_update_power_11n(int8_t * power_rate_table); +void trpc_update_vs_channel(int8_t channel_MHz); +void trpc_update_vs_temperature(int8_t temperature); #endif \ No newline at end of file From 1ffd6cbc31f637e2c4b590e04606f5105f10fcc4 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 25 Jul 2021 02:23:47 -0500 Subject: [PATCH 046/148] fix redefinition and memset --- src/bl602_wifi/bl602_rf_private.h | 4 ++-- src/bl602_wifi/phy_tcal.c | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/bl602_wifi/bl602_rf_private.h b/src/bl602_wifi/bl602_rf_private.h index bead91b..27a630f 100644 --- a/src/bl602_wifi/bl602_rf_private.h +++ b/src/bl602_wifi/bl602_rf_private.h @@ -2,12 +2,12 @@ #define _BL602_RF_PRIVATE_H_ #include -struct anon_struct { +struct anon_struct1 { uint32_t index; int32_t dvga; }; -typedef struct anon_struct anon_struct; +typedef struct anon_struct1 anon_struct1; struct anon_struct { uint32_t vbcore; diff --git a/src/bl602_wifi/phy_tcal.c b/src/bl602_wifi/phy_tcal.c index 980727e..5d625b8 100644 --- a/src/bl602_wifi/phy_tcal.c +++ b/src/bl602_wifi/phy_tcal.c @@ -3,6 +3,7 @@ #include "phy_bl602.h" #include "phy_trpc.h" #include "bl602_rf_private.h" +#include "utils.h" static struct tcal_tag tcal_env; // :41:24 From 184aa2caf5cf95f614a75dff92e1431540d5d6c3 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 25 Jul 2021 02:29:13 -0500 Subject: [PATCH 047/148] using rv32 and c11 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c60843..c5f600a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ set(CMAKE_SYSTEM_PROCESSOR riscv) SET(CMAKE_CROSSCOMPILING 1) set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") - +add_compile_options(-std=c11 -march=rv32imfc -mabi=ilp32f) project(bl602_re VERSION 0.1.0) include_directories(./src/include) From f4959fc0ae1a4060c9ad6d5e78d41772818a62de Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 25 Jul 2021 02:29:37 -0500 Subject: [PATCH 048/148] add memcpy and min/max --- src/bl602_wifi/utils.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/bl602_wifi/utils.h b/src/bl602_wifi/utils.h index 68cdca3..6a71b76 100644 --- a/src/bl602_wifi/utils.h +++ b/src/bl602_wifi/utils.h @@ -1,5 +1,9 @@ #ifndef __UTILS_H_ #define ABS(x) (((x) > 0) ? (x) : (-(x))) +#define MIN(x,y) (((x) > (y)) ? (y) : (x)) +#define MAX(x,y) (((x) < (y)) ? (y) : (x)) int puts(char *s); int printf(char *fmt,...); +void* memset(void *, int, long unsigned int); +void* memcpy(void*, const void*, unsigned int); #endif \ No newline at end of file From f20f2555f4f3ae3aad94409c464aa373aa45cb3a Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 25 Jul 2021 02:43:37 -0500 Subject: [PATCH 049/148] fix type --- src/bl602_wifi/phy_trpc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bl602_wifi/phy_trpc.c b/src/bl602_wifi/phy_trpc.c index 5ac8e0d..cd7a453 100644 --- a/src/bl602_wifi/phy_trpc.c +++ b/src/bl602_wifi/phy_trpc.c @@ -45,9 +45,9 @@ uint8_t trpc_get_power_idx(uint8_t formatmod, uint8_t mcs, int8_t pwr_dbm) { if (formatmod) { y = 0; } - x = (y + x) & 0xff; - if (x > 0xf) - x = 0xf; + uint32_t z = (y + x) & 0xff; + if (z > 0xf) + z = 0xf; return x << 2; } From 9079d1ea7c78d4e60cd52b8fc9c403430f5b96a4 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 25 Jul 2021 03:22:30 -0500 Subject: [PATCH 050/148] add phyif_utils --- src/bl602_wifi/phyif_utils.c | 56 ++++++++++++++++++++++++++++++++++++ src/bl602_wifi/phyif_utils.h | 16 +++++++++++ 2 files changed, 72 insertions(+) create mode 100644 src/bl602_wifi/phyif_utils.c create mode 100644 src/bl602_wifi/phyif_utils.h diff --git a/src/bl602_wifi/phyif_utils.c b/src/bl602_wifi/phyif_utils.c new file mode 100644 index 0000000..92e0623 --- /dev/null +++ b/src/bl602_wifi/phyif_utils.c @@ -0,0 +1,56 @@ +#include "phyif_utils.h" + +typedef struct { + uint32_t leg_length:12; // +0 + uint32_t leg_rate:4; // +0 + uint32_t ht_length:16; // +0 + uint32_t _ht_length:4; // +4 + uint32_t short_gi:1; // +4 + uint32_t stbc:2; // +4 + uint32_t smoothing:1; // +4 + uint32_t mcs:7; // +4 + uint32_t pre_type:1; // +4 + uint32_t format_mod:3; // +4 + uint32_t ch_bw:2; // +4 + uint32_t n_sts:3; // +4 + uint32_t lsig_valid:1; // +4 + uint32_t sounding:1; // +4 + uint32_t num_extn_ss:2; // +4 + uint32_t aggregation:1; // +4 + uint32_t fec_coding:1; // +4 + uint32_t dyn_bw:1; // +4 + uint32_t doze_not_allowed:1; // +4 + uint32_t antenna_set:8; // +8 + uint32_t partial_aid:9; // +8 + uint32_t group_id:6; // +8 + uint32_t reserved_1c:1; // +8 + int32_t rssi1:8; // +8 + int32_t rssi2:8; // +12 + union { + int32_t rssi34:16; + struct { + int32_t rssi3:8; // +12 + int32_t rssi4:8; // +12 + }; + }; + uint32_t reserved_1d:8; // +12 + uint32_t rcpi:8; // +16 + uint32_t evm1:8; // +16 + uint32_t evm2:8; // +16 + uint32_t evm3:8; // +16 + uint32_t evm4:8; // +20 + uint32_t reserved2b_1:8; // +20 + uint32_t reserved2b_2:8; // +20 + uint32_t reserved2b_3:8; // +20 +} phyif_utils_recvtable_priv_t; // :47:3 + +int phyif_utils_decode(phyif_utils_recvtable_t *vec,int8_t *ppm) { + phyif_utils_recvtable_priv_t* pvec = (phyif_utils_recvtable_priv_t*) vec; + int8_t vppm = 0; + if (pvec->format_mod < 2 && pvec->leg_rate < 4) { + vppm = (int)((double)(-(int)pvec->rssi3) * 0.7); + } else { + vppm = ((int)pvec->rssi34 / 0x7a); + } + *ppm = vppm; +} diff --git a/src/bl602_wifi/phyif_utils.h b/src/bl602_wifi/phyif_utils.h new file mode 100644 index 0000000..25f31ee --- /dev/null +++ b/src/bl602_wifi/phyif_utils.h @@ -0,0 +1,16 @@ +#ifndef _PHYIF_H_ +#define _PHYIF_H_ + +#include + +typedef struct { + uint32_t recvtable1; // +0 + uint32_t recvtable2; // +4 + uint32_t recvtable3; // +8 + uint32_t recvtable4; // +12 + uint32_t recvtable5; // +16 + uint32_t recvtable6; // +20 +} phyif_utils_recvtable_t; // :11:3 +int phyif_utils_decode(phyif_utils_recvtable_t *vec,int8_t *ppm); + +#endif \ No newline at end of file From 0a747be4c9d3f87a037ff3f111e369851c44a4f1 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 25 Jul 2021 03:57:58 -0500 Subject: [PATCH 051/148] add rf --- src/bl602_wifi/rf.c | 24 ++++++++++++++++++++++++ src/bl602_wifi/rf.h | 5 +++++ src/bl602_wifi/rfc_bl602.h | 1 + 3 files changed, 30 insertions(+) create mode 100644 src/bl602_wifi/rf.c diff --git a/src/bl602_wifi/rf.c b/src/bl602_wifi/rf.c new file mode 100644 index 0000000..8c6b786 --- /dev/null +++ b/src/bl602_wifi/rf.c @@ -0,0 +1,24 @@ +#include "rf.h" +#include "rfc_bl602.h" + +void rf_set_channel(uint8_t bandwidth, uint16_t channel_freq) { + rfc_config_channel(channel_freq); +} + +void rf_clkpll_isr(void) { + return ; +} + +void rf_init(void) { + __asm( + "csrrci a5, mstatus, 0x8\n\t" + "andi a5, a5, 0x8\n\t" + "beqz a5, .L0\n\t" + "csrrsi zero, mstatus, 0x8\n\t" + ".L0:" + ); +} + +void rf_lo_isr(void) { + return ; +} diff --git a/src/bl602_wifi/rf.h b/src/bl602_wifi/rf.h index d73cf2d..28a73df 100644 --- a/src/bl602_wifi/rf.h +++ b/src/bl602_wifi/rf.h @@ -1,4 +1,9 @@ #ifndef _RF_H_ #define _RF_H_ +#include + void rf_set_channel(uint8_t bandwidth, uint16_t channel_freq); +void rf_clkpll_isr(void); +void rf_init(void); +void rf_lo_isr(void); #endif \ No newline at end of file diff --git a/src/bl602_wifi/rfc_bl602.h b/src/bl602_wifi/rfc_bl602.h index 2387da6..662a78f 100644 --- a/src/bl602_wifi/rfc_bl602.h +++ b/src/bl602_wifi/rfc_bl602.h @@ -2,4 +2,5 @@ #define _RFC_BL602_H_ uint32_t rfc_get_power_level(uint32_t formatmod, int32_t power); // :1479:10 void rfc_apply_tx_power_offset(uint8_t channel, int8_t *power_offset); // :1643:6 +void rfc_config_channel(uint32_t channel_freq); #endif \ No newline at end of file From 7144472877a0fe49be1083ca5fb93222f56ae41d Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 25 Jul 2021 04:07:15 -0500 Subject: [PATCH 052/148] typo --- src/bl602_wifi/phy_trpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bl602_wifi/phy_trpc.c b/src/bl602_wifi/phy_trpc.c index cd7a453..34b34f4 100644 --- a/src/bl602_wifi/phy_trpc.c +++ b/src/bl602_wifi/phy_trpc.c @@ -48,7 +48,7 @@ uint8_t trpc_get_power_idx(uint8_t formatmod, uint8_t mcs, int8_t pwr_dbm) { uint32_t z = (y + x) & 0xff; if (z > 0xf) z = 0xf; - return x << 2; + return z << 2; } int8_t trpc_get_rf_max_power() { From 306eed0adee7cc02404f968f67f0ba6605067150 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 25 Jul 2021 18:56:49 -0500 Subject: [PATCH 053/148] update phy --- src/bl602_wifi/phy_trpc.c | 9 +- src/bl602_wifi/rfc_bl602.c | 169 +++++++++++++++++++++++++++++++++++++ src/bl602_wifi/rfc_bl602.h | 3 + src/bl602_wifi/utils.h | 1 + 4 files changed, 176 insertions(+), 6 deletions(-) create mode 100644 src/bl602_wifi/rfc_bl602.c diff --git a/src/bl602_wifi/phy_trpc.c b/src/bl602_wifi/phy_trpc.c index 34b34f4..ca204b4 100644 --- a/src/bl602_wifi/phy_trpc.c +++ b/src/bl602_wifi/phy_trpc.c @@ -40,12 +40,9 @@ uint8_t trpc_get_power_idx(uint8_t formatmod, uint8_t mcs, int8_t pwr_dbm) { pwr = MIN(pwr, pwr_dbm); pwr = MIN(pwr, txpwr_vs_rate_table[formatmod][mcs]); pwr = MAX(pwr, trpc_env.power_dbm_min_rf); - int x = (int)(((double)((int)(pwr * -510 + trpc_env.power_dbm_max_rf) / 512)) + (double)0.5) & 0xff; - int y = 3; - if (formatmod) { - y = 0; - } - uint32_t z = (y + x) & 0xff; + uint8_t z = trpc_env.power_dbm_max_rf - pwr; + if (formatmod == PHY_FORMATMOD_11B) + z += 3; if (z > 0xf) z = 0xf; return z << 2; diff --git a/src/bl602_wifi/rfc_bl602.c b/src/bl602_wifi/rfc_bl602.c new file mode 100644 index 0000000..c16622e --- /dev/null +++ b/src/bl602_wifi/rfc_bl602.c @@ -0,0 +1,169 @@ + +#include "rfc_bl602.h" +#include "bl602_rf_private.h" +#include "utils.h" + +#include + +void rfc_apply_tx_power_offset(uint8_t channel, int8_t *power_offset){ + rf_pri_update_tx_power_offset(channel, power_offset); + uint32_t rfg_index, dg; + rf_pri_query_txgain_table(0, &rfg_index, &dg); + RF->dfe_ctrl_16.rf_tbb_ind_gc0 = rfg_index & 7; + RF->dfe_ctrl_12.tx_dvga_gain_qdb_gc0 = dg; + rf_pri_query_txgain_table(1, &rfg_index, &dg); + RF->dfe_ctrl_16.rf_tbb_ind_gc1 = rfg_index & 7; + RF->dfe_ctrl_12.tx_dvga_gain_qdb_gc1 = dg; + rf_pri_query_txgain_table(2, &rfg_index, &dg); + RF->dfe_ctrl_16.rf_tbb_ind_gc2 = rfg_index & 7; + RF->dfe_ctrl_12.tx_dvga_gain_qdb_gc2 = dg; + rf_pri_query_txgain_table(3, &rfg_index, &dg); + RF->dfe_ctrl_16.rf_tbb_ind_gc3 = rfg_index & 7; + RF->dfe_ctrl_12.tx_dvga_gain_qdb_gc3 = dg; + rf_pri_query_txgain_table(4, &rfg_index, &dg); + RF->dfe_ctrl_16.rf_tbb_ind_gc4 = rfg_index & 7; + RF->dfe_ctrl_13.tx_dvga_gain_qdb_gc4 = dg; + rf_pri_query_txgain_table(5, &rfg_index, &dg); + RF->dfe_ctrl_16.rf_tbb_ind_gc5 = rfg_index & 7; + RF->dfe_ctrl_13.tx_dvga_gain_qdb_gc5 = dg; + rf_pri_query_txgain_table(6, &rfg_index, &dg); + RF->dfe_ctrl_16.rf_tbb_ind_gc6 = rfg_index & 7; + RF->dfe_ctrl_13.tx_dvga_gain_qdb_gc6 = dg; + rf_pri_query_txgain_table(7, &rfg_index, &dg); + RF->dfe_ctrl_16.rf_tbb_ind_gc7 = rfg_index & 7; + RF->dfe_ctrl_13.tx_dvga_gain_qdb_gc7 = dg; + rf_pri_query_txgain_table(8, &rfg_index, &dg); + RF->dfe_ctrl_17.rf_tbb_ind_gc8 = rfg_index & 7; + RF->dfe_ctrl_14.tx_dvga_gain_qdb_gc8 = dg; + rf_pri_query_txgain_table(9, &rfg_index, &dg); + RF->dfe_ctrl_17.rf_tbb_ind_gc9 = rfg_index & 7; + RF->dfe_ctrl_14.tx_dvga_gain_qdb_gc9 = dg; + rf_pri_query_txgain_table(10, &rfg_index, &dg); + RF->dfe_ctrl_17.rf_tbb_ind_gc10 = rfg_index & 7; + RF->dfe_ctrl_14.tx_dvga_gain_qdb_gc10 = dg; + rf_pri_query_txgain_table(11, &rfg_index, &dg); + RF->dfe_ctrl_17.rf_tbb_ind_gc11 = rfg_index & 7; + RF->dfe_ctrl_14.tx_dvga_gain_qdb_gc11 = dg; + rf_pri_query_txgain_table(12, &rfg_index, &dg); + RF->dfe_ctrl_17.rf_tbb_ind_gc12 = rfg_index & 7; + RF->dfe_ctrl_15.tx_dvga_gain_qdb_gc12 = dg; + rf_pri_query_txgain_table(13, &rfg_index, &dg); + RF->dfe_ctrl_17.rf_tbb_ind_gc13 = rfg_index & 7; + RF->dfe_ctrl_15.tx_dvga_gain_qdb_gc13 = dg; + rf_pri_query_txgain_table(14, &rfg_index, &dg); + RF->dfe_ctrl_17.rf_tbb_ind_gc14 = rfg_index & 7; + RF->dfe_ctrl_15.tx_dvga_gain_qdb_gc14 = dg; + rf_pri_query_txgain_table(15, &rfg_index, &dg); + RF->dfe_ctrl_17.rf_tbb_ind_gc15 = rfg_index & 7; + RF->dfe_ctrl_15.tx_dvga_gain_qdb_gc15 = dg; + +} + + + +void rfc_apply_tx_dvga(int8_t *dvga_qdb) { + RF->dfe_ctrl_12.tx_dvga_gain_qdb_gc0 = dvga_qdb[0]; + RF->dfe_ctrl_12.tx_dvga_gain_qdb_gc1 = dvga_qdb[1]; + RF->dfe_ctrl_12.tx_dvga_gain_qdb_gc2 = dvga_qdb[2]; + RF->dfe_ctrl_12.tx_dvga_gain_qdb_gc3 = dvga_qdb[3]; + + RF->dfe_ctrl_13.tx_dvga_gain_qdb_gc4 = dvga_qdb[4]; + RF->dfe_ctrl_13.tx_dvga_gain_qdb_gc5 = dvga_qdb[5]; + RF->dfe_ctrl_13.tx_dvga_gain_qdb_gc6 = dvga_qdb[6]; + RF->dfe_ctrl_13.tx_dvga_gain_qdb_gc7 = dvga_qdb[7]; + + RF->dfe_ctrl_14.tx_dvga_gain_qdb_gc8 = dvga_qdb[8]; + RF->dfe_ctrl_14.tx_dvga_gain_qdb_gc9 = dvga_qdb[9]; + RF->dfe_ctrl_14.tx_dvga_gain_qdb_gc10 = dvga_qdb[10]; + RF->dfe_ctrl_14.tx_dvga_gain_qdb_gc11 = dvga_qdb[11]; + + RF->dfe_ctrl_15.tx_dvga_gain_qdb_gc12 = dvga_qdb[12]; + RF->dfe_ctrl_15.tx_dvga_gain_qdb_gc13 = dvga_qdb[13]; + RF->dfe_ctrl_15.tx_dvga_gain_qdb_gc14 = dvga_qdb[14]; + RF->dfe_ctrl_15.tx_dvga_gain_qdb_gc15 = dvga_qdb[15]; +} + +void rfc_coex_force_to(uint32_t force_enable, uint32_t bbmode) { + RF->rf_fsm_ctrl_hw.rf_fsm_ctrl_en = 0; + wait_us(10); + RF->rfif_dfe_ctrl0.bbmode_4s = bbmode & 1; + RF->rfif_dfe_ctrl0.bbmode_4s_en = (force_enable != 0); +} + +void rfc_config_channel(uint32_t channel_freq) { + RF->rfif_dig_ctrl.rfif_int_lo_unlocked_mask = 1; + RF->rfctrl_hw_en.lo_ctrl_hw = 1; + RF->rfctrl_hw_en.sdm_ctrl_hw = 1; + RF->rfctrl_hw_en.pu_ctrl_hw = 1; + RF->rf_fsm_ctrl0.rf_ch_ind_wifi = channel_freq & 0xfff; + RF->rf_fsm_ctrl1.rf_fsm_lo_rdy_rst = 1; + wait_us(10); + RF->rf_fsm_ctrl1.rf_fsm_lo_rdy_rst = 0; + wait_us(10); + RF->rf_fsm_ctrl_hw.rf_fsm_ctrl_en = 0; + wait_us(10); + RF->rf_fsm_ctrl_hw.rf_fsm_ctrl_en = 1; + wait_us(10); + RF->rf_fsm_ctrl2.rf_fsm_st_dbg = 1; + wait_us(10); + RF->rf_fsm_ctrl2.rf_fsm_st_dbg_en = 1; + wait_us(10); + RF->rf_fsm_ctrl2.rf_fsm_st_dbg = 2; + wait_us(100); + RF->rf_fsm_ctrl2.rf_fsm_st_dbg_en = 0; + wait_us(10); + _print_channel_info(); + rf_pri_update_param(channel_freq); + uint8_t ncf_on; + int32_t ncf_freq_Hz; + rf_pri_get_notch_param(channel_freq, &ncf_on, (int32_t *)&ncf_freq_Hz); + double freq = ncf_freq_Hz; + freq /= 40000000.0; + freq *= 256.0; + freq += 0.5; + int32_t new_freq = freq; + rfc_rxdfe_set_notch0(ncf_on, 1, new_freq); + RF->rfif_dig_ctrl.rfif_int_lo_unlocked_mask = 0; +} + +uint32_t rfc_get_power_level(uint32_t formatmod, int32_t power) { + if (formatmod > 2) + formatmod = 0; + return rf_pri_get_txgain_index(power, formatmod) << 2; +} + +void rfc_init(uint32_t xtalfreq_hz) { + RF->rfif_dfe_ctrl0.bbmode_4s = 0; + RF->rfif_dfe_ctrl0.bbmode_4s_en = 1; + int xtal_mode = 2; + if (xtalfreq_hz != 32000000) { + if (xtalfreq_hz < 0x1e84801) { + xtal_mode = 0; + if (xtalfreq_hz == 24000000) { + xtal_mode = 1; + } else { + xtal_mode = 4; + } + } else { + if (xtalfreq_hz != 40000000) { + xtal_mode = 5; + if (xtalfreq_hz != 52000000) { + if (xtalfreq_hz == 38400000) { + xtal_mode = 3; + } else { + xtal_mode = 4; + } + } + } + } + } +} + +void _print_channel_info() { + for (int i = 0; i < 8; i++) { + wait_us(1000); + } + for (int i = 0; i < 8; i++) { + wait_us(1000); + } +} \ No newline at end of file diff --git a/src/bl602_wifi/rfc_bl602.h b/src/bl602_wifi/rfc_bl602.h index 662a78f..51987a9 100644 --- a/src/bl602_wifi/rfc_bl602.h +++ b/src/bl602_wifi/rfc_bl602.h @@ -1,6 +1,9 @@ #ifndef _RFC_BL602_H_ #define _RFC_BL602_H_ +#include uint32_t rfc_get_power_level(uint32_t formatmod, int32_t power); // :1479:10 void rfc_apply_tx_power_offset(uint8_t channel, int8_t *power_offset); // :1643:6 void rfc_config_channel(uint32_t channel_freq); +void rfc_apply_tx_dvga(int8_t *dvga_qdb); +void _print_channel_info(); #endif \ No newline at end of file diff --git a/src/bl602_wifi/utils.h b/src/bl602_wifi/utils.h index 6a71b76..0129ee6 100644 --- a/src/bl602_wifi/utils.h +++ b/src/bl602_wifi/utils.h @@ -6,4 +6,5 @@ int puts(char *s); int printf(char *fmt,...); void* memset(void *, int, long unsigned int); void* memcpy(void*, const void*, unsigned int); +void wait_us(uint32_t us); #endif \ No newline at end of file From c2828b0247129bfa6b970772b8f3ff1776ea1a27 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Mon, 26 Jul 2021 00:10:32 -0500 Subject: [PATCH 054/148] update rf header --- src/include/soc/rf.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/include/soc/rf.h b/src/include/soc/rf.h index a0061d4..ee0c812 100644 --- a/src/include/soc/rf.h +++ b/src/include/soc/rf.h @@ -1915,6 +1915,19 @@ typedef union { uint32_t pad2 : 9; }; } dfe_ctrl_18; // @ 0x648 + uint8_t pad4[0xb4]; + union { + uint32_t value; + struct { + uint32_t rf_rx_notch0_alpha : 3; // @ 2 -- 0 # 0xfffffff8 + uint32_t rf_rx_notch1_alpha : 3; // @ 5 -- 3 # 0xffffffc7 + uint32_t rf_rx_notch0_en : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t rf_rx_notch1_en : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t rf_rx_notch0_nrmfc : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t rf_rx_notch1_nrmfc : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t pad0 : 8; + }; + } r0x1700; // @ 0x700 }; } rf_regs; #define RF_BASE 0x40001000 From ddf961547b39f7ccd8526057f7ce0c66f7a48ae1 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Fri, 30 Jul 2021 00:04:50 -0500 Subject: [PATCH 055/148] back to * -510 --- src/bl602_wifi/phy_trpc.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/bl602_wifi/phy_trpc.c b/src/bl602_wifi/phy_trpc.c index ca204b4..ac39fe9 100644 --- a/src/bl602_wifi/phy_trpc.c +++ b/src/bl602_wifi/phy_trpc.c @@ -40,12 +40,15 @@ uint8_t trpc_get_power_idx(uint8_t formatmod, uint8_t mcs, int8_t pwr_dbm) { pwr = MIN(pwr, pwr_dbm); pwr = MIN(pwr, txpwr_vs_rate_table[formatmod][mcs]); pwr = MAX(pwr, trpc_env.power_dbm_min_rf); - uint8_t z = trpc_env.power_dbm_max_rf - pwr; + int x = (int)(((double)((int)(pwr * -510 + trpc_env.power_dbm_max_rf) / 512)) + (double)0.5) & 0xff; + if (formatmod == PHY_FORMATMOD_11B) - z += 3; - if (z > 0xf) - z = 0xf; - return z << 2; + x += 3; + x &= 0xff; + if (x > 0xf) + x = 0xf; + + return x << 2; } int8_t trpc_get_rf_max_power() { From 29e8a774cfddbd64ae2d9b12963f2263ff4cd176 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 22 Sep 2021 01:51:45 -0500 Subject: [PATCH 056/148] fix ; --- src/bl602_wifi/utils.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bl602_wifi/utils.h b/src/bl602_wifi/utils.h index 0129ee6..932abb2 100644 --- a/src/bl602_wifi/utils.h +++ b/src/bl602_wifi/utils.h @@ -7,4 +7,5 @@ int printf(char *fmt,...); void* memset(void *, int, long unsigned int); void* memcpy(void*, const void*, unsigned int); void wait_us(uint32_t us); +void BL602_Delay_US(uint32_t cnt); #endif \ No newline at end of file From ceb548b6cc13ef24949cedbd9c1f84f3c03e4f5c Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Thu, 28 Oct 2021 00:43:00 -0500 Subject: [PATCH 057/148] headers for SOC --- src/include/soc/HBN.h | 209 +++++++++++ src/include/soc/cci.h | 50 +++ src/include/soc/cks.h | 30 ++ src/include/soc/dma.h | 304 ++++++++++++++++ src/include/soc/ef_ctrl.h | 190 ++++++++++ src/include/soc/ef_data_0.h | 238 +++++++++++++ src/include/soc/ef_data_1.h | 130 +++++++ src/include/soc/gpip.h | 82 +++++ src/include/soc/i2c.h | 142 ++++++++ src/include/soc/ir.h | 195 +++++++++++ src/include/soc/l1c.h | 84 +++++ src/include/soc/pds.h | 284 +++++++++++++++ src/include/soc/pwm.h | 267 +++++++++++++++ src/include/soc/sec_dbg.h | 62 ++++ src/include/soc/sec_eng.h | 624 +++++++++++++++++++++++++++++++++ src/include/soc/sf_ctrl.h | 667 ++++++++++++++++++++++++++++++++++++ src/include/soc/spi.h | 139 ++++++++ src/include/soc/timer.h | 284 +++++++++++++++ src/include/soc/tzc_nsec.h | 62 ++++ src/include/soc/tzc_sec.h | 62 ++++ src/include/soc/uart.h | 192 +++++++++++ 21 files changed, 4297 insertions(+) create mode 100644 src/include/soc/HBN.h create mode 100644 src/include/soc/cci.h create mode 100644 src/include/soc/cks.h create mode 100644 src/include/soc/dma.h create mode 100644 src/include/soc/ef_ctrl.h create mode 100644 src/include/soc/ef_data_0.h create mode 100644 src/include/soc/ef_data_1.h create mode 100644 src/include/soc/gpip.h create mode 100644 src/include/soc/i2c.h create mode 100644 src/include/soc/ir.h create mode 100644 src/include/soc/l1c.h create mode 100644 src/include/soc/pds.h create mode 100644 src/include/soc/pwm.h create mode 100644 src/include/soc/sec_dbg.h create mode 100644 src/include/soc/sec_eng.h create mode 100644 src/include/soc/sf_ctrl.h create mode 100644 src/include/soc/spi.h create mode 100644 src/include/soc/timer.h create mode 100644 src/include/soc/tzc_nsec.h create mode 100644 src/include/soc/tzc_sec.h create mode 100644 src/include/soc/uart.h diff --git a/src/include/soc/HBN.h b/src/include/soc/HBN.h new file mode 100644 index 0000000..819f0e5 --- /dev/null +++ b/src/include/soc/HBN.h @@ -0,0 +1,209 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + union { + uint32_t value; + struct { + uint32_t rtc_ctl : 7; // @ 6 -- 0 # 0xffffff80 + uint32_t hbn_mode : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t trap_mode : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pwrdn_hbn_core : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t pad0 : 1; + uint32_t pwrdn_hbn_rtc : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t sw_rst : 1; // @ 12 -- 12 # 0xffffefff + uint32_t hbn_dis_pwr_off_ldo11 : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t hbn_dis_pwr_off_ldo11_rt : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t hbn_ldo11_rt_vout_sel : 4; // @ 18 -- 15 # 0xfff87fff + uint32_t hbn_ldo11_aon_vout_sel : 4; // @ 22 -- 19 # 0xff87ffff + uint32_t pu_dcdc18_aon : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t rtc_dly_option : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t pwr_on_option : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t sram_slp_option : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t sram_slp : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t hbn_state : 4; // @ 31 -- 28 # 0xfffffff + }; + } HBN_CTL; // @ 0x0 + union { + uint32_t value; + struct { + uint32_t hbn_time_l : 32; // @ 31 -- 0 # 0x0 + }; + } HBN_TIME_L; // @ 0x4 + union { + uint32_t value; + struct { + uint32_t hbn_time_h : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pad0 : 24; + }; + } HBN_TIME_H; // @ 0x8 + union { + uint32_t value; + struct { + uint32_t rtc_time_latch_l : 32; // @ 31 -- 0 # 0x0 + }; + } RTC_TIME_L; // @ 0xc + union { + uint32_t value; + struct { + uint32_t rtc_time_latch_h : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pad0 : 23; + uint32_t rtc_time_latch : 1; // @ 31 -- 31 # 0x7fffffff + }; + } RTC_TIME_H; // @ 0x10 + union { + uint32_t value; + struct { + uint32_t hbn_pin_wakeup_mode : 3; // @ 2 -- 0 # 0xfffffff8 + uint32_t hbn_pin_wakeup_mask : 2; // @ 4 -- 3 # 0xffffffe7 + uint32_t pad0 : 3; + uint32_t reg_aon_pad_ie_smt : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pad1 : 7; + uint32_t reg_en_hw_pu_pd : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad2 : 1; + uint32_t irq_bor_en : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t pad3 : 1; + uint32_t irq_acomp0_en : 2; // @ 21 -- 20 # 0xffcfffff + uint32_t irq_acomp1_en : 2; // @ 23 -- 22 # 0xff3fffff + uint32_t pin_wakeup_sel : 3; // @ 26 -- 24 # 0xf8ffffff + uint32_t pin_wakeup_en : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t pad4 : 4; + }; + } HBN_IRQ_MODE; // @ 0x14 + union { + uint32_t value; + struct { + uint32_t irq_stat : 32; // @ 31 -- 0 # 0x0 + }; + } HBN_IRQ_STAT; // @ 0x18 + union { + uint32_t value; + struct { + uint32_t irq_clr : 32; // @ 31 -- 0 # 0x0 + }; + } HBN_IRQ_CLR; // @ 0x1c + union { + uint32_t value; + struct { + uint32_t pir_hpf_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pir_lpf_sel : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 1; + uint32_t pir_dis : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t pad1 : 1; + uint32_t pir_en : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t gpadc_cgen : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t gpadc_nosync : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t pad2 : 22; + }; + } HBN_PIR_CFG; // @ 0x20 + union { + uint32_t value; + struct { + uint32_t pir_vth : 14; // @ 13 -- 0 # 0xffffc000 + uint32_t pad0 : 18; + }; + } HBN_PIR_VTH; // @ 0x24 + union { + uint32_t value; + struct { + uint32_t pir_interval : 12; // @ 11 -- 0 # 0xfffff000 + uint32_t pad0 : 20; + }; + } HBN_PIR_INTERVAL; // @ 0x28 + union { + uint32_t value; + struct { + uint32_t bor_sel : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t bor_vth : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t pu_bor : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t r_bor_out : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pad0 : 28; + }; + } HBN_BOR_CFG; // @ 0x2c + union { + uint32_t value; + struct { + uint32_t hbn_root_clk_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t hbn_uart_clk_sel : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t hbn_f32k_sel : 2; // @ 4 -- 3 # 0xffffffe7 + uint32_t hbn_pu_rc32k : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad0 : 10; + uint32_t sw_ldo11soc_vout_sel_aon : 4; // @ 19 -- 16 # 0xfff0ffff + uint32_t pad1 : 4; + uint32_t sw_ldo11_rt_vout_sel : 4; // @ 27 -- 24 # 0xf0ffffff + uint32_t sw_ldo11_aon_vout_sel : 4; // @ 31 -- 28 # 0xfffffff + }; + } HBN_GLB; // @ 0x30 + union { + uint32_t value; + struct { + uint32_t pad0 : 6; + uint32_t retram_ret : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t retram_slp : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t pad1 : 24; + }; + } HBN_SRAM; // @ 0x34 + uint8_t pad0[0xc8]; + union { + uint32_t value; + struct { + uint32_t HBN_RSV0 : 32; // @ 31 -- 0 # 0x0 + }; + } HBN_RSV0; // @ 0x100 + union { + uint32_t value; + struct { + uint32_t HBN_RSV1 : 32; // @ 31 -- 0 # 0x0 + }; + } HBN_RSV1; // @ 0x104 + union { + uint32_t value; + struct { + uint32_t HBN_RSV2 : 32; // @ 31 -- 0 # 0x0 + }; + } HBN_RSV2; // @ 0x108 + union { + uint32_t value; + struct { + uint32_t HBN_RSV3 : 32; // @ 31 -- 0 # 0x0 + }; + } HBN_RSV3; // @ 0x10c + uint8_t pad1[0xf0]; + union { + uint32_t value; + struct { + uint32_t rc32k_cal_done : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t rc32k_rdy : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t rc32k_cal_inprogress : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t rc32k_cal_div : 2; // @ 4 -- 3 # 0xffffffe7 + uint32_t rc32k_cal_precharge : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t rc32k_dig_code_fr_cal : 10; // @ 15 -- 6 # 0xffff003f + uint32_t rc32k_vref_dly : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t rc32k_allow_cal : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t rc32k_ext_code_en : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t rc32k_cal_en : 1; // @ 20 -- 20 # 0xffefffff + uint32_t pad0 : 1; + uint32_t rc32k_code_fr_ext : 10; // @ 31 -- 22 # 0x3fffff + }; + } rc32k_ctrl0; // @ 0x200 + union { + uint32_t value; + struct { + uint32_t pad0 : 2; + uint32_t xtal32k_ext_sel : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t xtal32k_amp_ctrl : 2; // @ 4 -- 3 # 0xffffffe7 + uint32_t xtal32k_reg : 2; // @ 6 -- 5 # 0xffffff9f + uint32_t xtal32k_outbuf_stre : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t xtal32k_otf_short : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t xtal32k_inv_stre : 2; // @ 10 -- 9 # 0xfffff9ff + uint32_t xtal32k_capbank : 6; // @ 16 -- 11 # 0xfffe07ff + uint32_t xtal32k_ac_cap_short : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t pu_xtal32k_buf : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t pu_xtal32k : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t pad1 : 12; + }; + } xtal32k; // @ 0x204 + }; +} HBN_regs; +#define HBN_BASE 0x4000f000 +#define HBN ((HBN_regs* volatile)(HBN_BASE)) \ No newline at end of file diff --git a/src/include/soc/cci.h b/src/include/soc/cci.h new file mode 100644 index 0000000..d9d4def --- /dev/null +++ b/src/include/soc/cci.h @@ -0,0 +1,50 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + union { + uint32_t value; + struct { + uint32_t cci_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t cci_slv_sel_cci2 : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t cci_mas_sel_cci2 : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t cci_mas_hw_mode : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t reg_m_cci_sclk_en : 1; // @ 4 -- 4 # 0xffffffef + uint32_t reg_div_m_cci_sclk : 2; // @ 6 -- 5 # 0xffffff9f + uint32_t cfg_cci1_pre_read : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t reg_scci_clk_inv : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t reg_mcci_clk_inv : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t pad0 : 22; + }; + } cci_cfg; // @ 0x0 + union { + uint32_t value; + struct { + uint32_t apb_cci_addr : 32; // @ 31 -- 0 # 0x0 + }; + } cci_addr; // @ 0x4 + union { + uint32_t value; + struct { + uint32_t apb_cci_wdata : 32; // @ 31 -- 0 # 0x0 + }; + } cci_wdata; // @ 0x8 + union { + uint32_t value; + struct { + uint32_t apb_cci_rdata : 32; // @ 31 -- 0 # 0x0 + }; + } cci_rdata; // @ 0xc + union { + uint32_t value; + struct { + uint32_t cci_write_flag : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t cci_read_flag : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t ahb_state : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t pad0 : 28; + }; + } cci_ctl; // @ 0x10 + }; +} cci_regs; +#define CCI_BASE 0x40008000 +#define CCI ((cci_regs* volatile)(CCI_BASE)) \ No newline at end of file diff --git a/src/include/soc/cks.h b/src/include/soc/cks.h new file mode 100644 index 0000000..474e844 --- /dev/null +++ b/src/include/soc/cks.h @@ -0,0 +1,30 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + union { + uint32_t value; + struct { + uint32_t cr_cks_clr : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t cr_cks_byte_swap : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t pad0 : 30; + }; + } cks_config; // @ 0x0 + union { + uint32_t value; + struct { + uint32_t data_in : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pad0 : 24; + }; + } data_in; // @ 0x4 + union { + uint32_t value; + struct { + uint32_t cks_out : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } cks_out; // @ 0x8 + }; +} cks_regs; +#define CKS_BASE 0x4000a000 +#define CKS ((cks_regs* volatile)(CKS_BASE)) \ No newline at end of file diff --git a/src/include/soc/dma.h b/src/include/soc/dma.h new file mode 100644 index 0000000..8b88f88 --- /dev/null +++ b/src/include/soc/dma.h @@ -0,0 +1,304 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + union { + uint32_t value; + struct { + uint32_t IntStatus : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pad0 : 24; + }; + } DMA_IntStatus; // @ 0x0 + union { + uint32_t value; + struct { + uint32_t IntTCStatus : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pad0 : 24; + }; + } DMA_IntTCStatus; // @ 0x4 + union { + uint32_t value; + struct { + uint32_t IntTCClear : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pad0 : 24; + }; + } DMA_IntTCClear; // @ 0x8 + union { + uint32_t value; + struct { + uint32_t IntErrorStatus : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pad0 : 24; + }; + } DMA_IntErrorStatus; // @ 0xc + union { + uint32_t value; + struct { + uint32_t IntErrClr : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pad0 : 24; + }; + } DMA_IntErrClr; // @ 0x10 + union { + uint32_t value; + struct { + uint32_t RawIntTCStatus : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pad0 : 24; + }; + } DMA_RawIntTCStatus; // @ 0x14 + union { + uint32_t value; + struct { + uint32_t RawIntErrorStatus : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pad0 : 24; + }; + } DMA_RawIntErrorStatus; // @ 0x18 + union { + uint32_t value; + struct { + uint32_t EnabledChannels : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pad0 : 24; + }; + } DMA_EnbldChns; // @ 0x1c + union { + uint32_t value; + struct { + uint32_t SoftBReq : 32; // @ 31 -- 0 # 0x0 + }; + } DMA_SoftBReq; // @ 0x20 + union { + uint32_t value; + struct { + uint32_t SoftSReq : 32; // @ 31 -- 0 # 0x0 + }; + } DMA_SoftSReq; // @ 0x24 + union { + uint32_t value; + struct { + uint32_t SoftLBReq : 32; // @ 31 -- 0 # 0x0 + }; + } DMA_SoftLBReq; // @ 0x28 + union { + uint32_t value; + struct { + uint32_t SoftLSReq : 32; // @ 31 -- 0 # 0x0 + }; + } DMA_SoftLSReq; // @ 0x2c + union { + uint32_t value; + struct { + uint32_t E : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t M : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t pad0 : 30; + }; + } DMA_Top_Config; // @ 0x30 + union { + uint32_t value; + struct { + uint32_t DMA_Sync : 32; // @ 31 -- 0 # 0x0 + }; + } DMA_Sync; // @ 0x34 + uint8_t pad0[0xc8]; + union { + uint32_t value; + struct { + uint32_t SrcAddr : 32; // @ 31 -- 0 # 0x0 + }; + } DMA_C0SrcAddr; // @ 0x100 + union { + uint32_t value; + struct { + uint32_t DstAddr : 32; // @ 31 -- 0 # 0x0 + }; + } DMA_C0DstAddr; // @ 0x104 + union { + uint32_t value; + struct { + uint32_t LLI : 32; // @ 31 -- 0 # 0x0 + }; + } DMA_C0LLI; // @ 0x108 + union { + uint32_t value; + struct { + uint32_t TransferSize : 12; // @ 11 -- 0 # 0xfffff000 + uint32_t SBSize : 3; // @ 14 -- 12 # 0xffff8fff + uint32_t DBSize : 3; // @ 17 -- 15 # 0xfffc7fff + uint32_t SWidth : 3; // @ 20 -- 18 # 0xffe3ffff + uint32_t DWidth : 3; // @ 23 -- 21 # 0xff1fffff + uint32_t SLargerD : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t pad0 : 1; + uint32_t SI : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t DI : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t Prot : 3; // @ 30 -- 28 # 0x8fffffff + uint32_t I : 1; // @ 31 -- 31 # 0x7fffffff + }; + } DMA_C0Control; // @ 0x10c + union { + uint32_t value; + struct { + uint32_t E : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t SrcPeripheral : 5; // @ 5 -- 1 # 0xffffffc1 + uint32_t DstPeripheral : 5; // @ 10 -- 6 # 0xfffff83f + uint32_t FlowCntrl : 3; // @ 13 -- 11 # 0xffffc7ff + uint32_t IE : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t ITC : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t L : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t A : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t H : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t pad0 : 1; + uint32_t LLICounter : 10; // @ 29 -- 20 # 0xc00fffff + uint32_t pad1 : 2; + }; + } DMA_C0Config; // @ 0x110 + uint8_t pad1[0xec]; + union { + uint32_t value; + struct { + uint32_t SrcAddr : 32; // @ 31 -- 0 # 0x0 + }; + } DMA_C1SrcAddr; // @ 0x200 + union { + uint32_t value; + struct { + uint32_t DstAddr : 32; // @ 31 -- 0 # 0x0 + }; + } DMA_C1DstAddr; // @ 0x204 + union { + uint32_t value; + struct { + uint32_t pad0 : 2; + uint32_t LLI : 30; // @ 31 -- 2 # 0x3 + }; + } DMA_C1LLI; // @ 0x208 + union { + uint32_t value; + struct { + uint32_t TransferSize : 12; // @ 11 -- 0 # 0xfffff000 + uint32_t SBSize : 3; // @ 14 -- 12 # 0xffff8fff + uint32_t DBSize : 3; // @ 17 -- 15 # 0xfffc7fff + uint32_t SWidth : 3; // @ 20 -- 18 # 0xffe3ffff + uint32_t DWidth : 3; // @ 23 -- 21 # 0xff1fffff + uint32_t pad0 : 2; + uint32_t SI : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t DI : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t Prot : 3; // @ 30 -- 28 # 0x8fffffff + uint32_t I : 1; // @ 31 -- 31 # 0x7fffffff + }; + } DMA_C1Control; // @ 0x20c + union { + uint32_t value; + struct { + uint32_t E : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t SrcPeripheral : 5; // @ 5 -- 1 # 0xffffffc1 + uint32_t DstPeripheral : 5; // @ 10 -- 6 # 0xfffff83f + uint32_t FlowCntrl : 3; // @ 13 -- 11 # 0xffffc7ff + uint32_t IE : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t ITC : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t L : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t A : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t H : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t pad0 : 13; + }; + } DMA_C1Config; // @ 0x210 + uint8_t pad2[0xec]; + union { + uint32_t value; + struct { + uint32_t SrcAddr : 32; // @ 31 -- 0 # 0x0 + }; + } DMA_C2SrcAddr; // @ 0x300 + union { + uint32_t value; + struct { + uint32_t DstAddr : 32; // @ 31 -- 0 # 0x0 + }; + } DMA_C2DstAddr; // @ 0x304 + union { + uint32_t value; + struct { + uint32_t pad0 : 2; + uint32_t LLI : 30; // @ 31 -- 2 # 0x3 + }; + } DMA_C2LLI; // @ 0x308 + union { + uint32_t value; + struct { + uint32_t TransferSize : 12; // @ 11 -- 0 # 0xfffff000 + uint32_t SBSize : 3; // @ 14 -- 12 # 0xffff8fff + uint32_t DBSize : 3; // @ 17 -- 15 # 0xfffc7fff + uint32_t SWidth : 3; // @ 20 -- 18 # 0xffe3ffff + uint32_t DWidth : 3; // @ 23 -- 21 # 0xff1fffff + uint32_t pad0 : 2; + uint32_t SI : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t DI : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t Prot : 3; // @ 30 -- 28 # 0x8fffffff + uint32_t I : 1; // @ 31 -- 31 # 0x7fffffff + }; + } DMA_C2Control; // @ 0x30c + union { + uint32_t value; + struct { + uint32_t E : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t SrcPeripheral : 5; // @ 5 -- 1 # 0xffffffc1 + uint32_t DstPeripheral : 5; // @ 10 -- 6 # 0xfffff83f + uint32_t FlowCntrl : 3; // @ 13 -- 11 # 0xffffc7ff + uint32_t IE : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t ITC : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t L : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t A : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t H : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t pad0 : 13; + }; + } DMA_C2Config; // @ 0x310 + uint8_t pad3[0xec]; + union { + uint32_t value; + struct { + uint32_t SrcAddr : 32; // @ 31 -- 0 # 0x0 + }; + } DMA_C3SrcAddr; // @ 0x400 + union { + uint32_t value; + struct { + uint32_t DstAddr : 32; // @ 31 -- 0 # 0x0 + }; + } DMA_C3DstAddr; // @ 0x404 + union { + uint32_t value; + struct { + uint32_t pad0 : 2; + uint32_t LLI : 30; // @ 31 -- 2 # 0x3 + }; + } DMA_C3LLI; // @ 0x408 + union { + uint32_t value; + struct { + uint32_t TransferSize : 12; // @ 11 -- 0 # 0xfffff000 + uint32_t SBSize : 3; // @ 14 -- 12 # 0xffff8fff + uint32_t DBSize : 3; // @ 17 -- 15 # 0xfffc7fff + uint32_t SWidth : 3; // @ 20 -- 18 # 0xffe3ffff + uint32_t DWidth : 3; // @ 23 -- 21 # 0xff1fffff + uint32_t pad0 : 2; + uint32_t SI : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t DI : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t Prot : 3; // @ 30 -- 28 # 0x8fffffff + uint32_t I : 1; // @ 31 -- 31 # 0x7fffffff + }; + } DMA_C3Control; // @ 0x40c + union { + uint32_t value; + struct { + uint32_t E : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t SrcPeripheral : 5; // @ 5 -- 1 # 0xffffffc1 + uint32_t DstPeripheral : 5; // @ 10 -- 6 # 0xfffff83f + uint32_t FlowCntrl : 3; // @ 13 -- 11 # 0xffffc7ff + uint32_t IE : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t ITC : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t L : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t A : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t H : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t pad0 : 13; + }; + } DMA_C3Config; // @ 0x410 + }; +} dma_regs; +#define DMA_BASE 0x4000c000 +#define DMA ((dma_regs* volatile)(DMA_BASE)) \ No newline at end of file diff --git a/src/include/soc/ef_ctrl.h b/src/include/soc/ef_ctrl.h new file mode 100644 index 0000000..b2ef074 --- /dev/null +++ b/src/include/soc/ef_ctrl.h @@ -0,0 +1,190 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + uint8_t pad0[0x800]; + union { + uint32_t value; + struct { + uint32_t ef_if_0_autoload_p1_done : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t ef_if_0_autoload_done : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t ef_if_0_busy : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t ef_if_0_rw : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t ef_if_0_trig : 1; // @ 4 -- 4 # 0xffffffef + uint32_t ef_if_0_manual_en : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t ef_if_0_cyc_modify : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t ef_clk_sahb_data_sel : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t ef_if_prot_code_ctrl : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t ef_if_por_dig : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t ef_clk_sahb_data_gate : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t ef_if_auto_rd_en : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t ef_if_cyc_modify_lock : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t ef_if_0_int : 1; // @ 20 -- 20 # 0xffefffff + uint32_t ef_if_0_int_clr : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t ef_if_0_int_set : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t pad0 : 1; + uint32_t ef_if_prot_code_cyc : 8; // @ 31 -- 24 # 0xffffff + }; + } ef_if_ctrl_0; // @ 0x800 + union { + uint32_t value; + struct { + uint32_t ef_if_cyc_rd_dmy : 6; // @ 5 -- 0 # 0xffffffc0 + uint32_t ef_if_cyc_rd_dat : 6; // @ 11 -- 6 # 0xfffff03f + uint32_t ef_if_cyc_rd_adr : 6; // @ 17 -- 12 # 0xfffc0fff + uint32_t ef_if_cyc_cs : 6; // @ 23 -- 18 # 0xff03ffff + uint32_t ef_if_cyc_pd_cs_s : 8; // @ 31 -- 24 # 0xffffff + }; + } ef_if_cyc_0; // @ 0x804 + union { + uint32_t value; + struct { + uint32_t ef_if_cyc_pi : 6; // @ 5 -- 0 # 0xffffffc0 + uint32_t ef_if_cyc_pp : 8; // @ 13 -- 6 # 0xffffc03f + uint32_t ef_if_cyc_wr_adr : 6; // @ 19 -- 14 # 0xfff03fff + uint32_t ef_if_cyc_ps_cs : 6; // @ 25 -- 20 # 0xfc0fffff + uint32_t ef_if_cyc_pd_cs_h : 6; // @ 31 -- 26 # 0x3ffffff + }; + } ef_if_cyc_1; // @ 0x808 + union { + uint32_t value; + struct { + uint32_t ef_if_a : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t ef_if_pd : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t ef_if_ps : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t ef_if_strobe : 1; // @ 12 -- 12 # 0xffffefff + uint32_t ef_if_pgenb : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t ef_if_load : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t ef_if_csb : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t ef_if_0_q : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t ef_if_prot_code_manual : 8; // @ 31 -- 24 # 0xffffff + }; + } ef_if_0_manual; // @ 0x80c + union { + uint32_t value; + struct { + uint32_t ef_if_0_status : 32; // @ 31 -- 0 # 0x0 + }; + } ef_if_0_status; // @ 0x810 + union { + uint32_t value; + struct { + uint32_t ef_if_sf_aes_mode : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t ef_if_sboot_sign_mode : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t ef_if_sboot_en : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t ef_if_cpu1_enc_en : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t ef_if_cpu0_enc_en : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t ef_if_boot_sel : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t ef_if_sw_usage_1 : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t ef_if_sdu_dis : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t ef_if_ble_dis : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t ef_if_wifi_dis : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t ef_if_0_key_enc_en : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t ef_if_cam_dis : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t ef_if_sf_dis : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t ef_if_cpu1_dis : 1; // @ 20 -- 20 # 0xffefffff + uint32_t ef_if_cpu_rst_dbg_dis : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t ef_if_se_dbg_dis : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t ef_if_efuse_dbg_dis : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t ef_if_dbg_jtag_1_dis : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t ef_if_dbg_jtag_0_dis : 2; // @ 27 -- 26 # 0xf3ffffff + uint32_t ef_if_dbg_mode : 4; // @ 31 -- 28 # 0xfffffff + }; + } ef_if_cfg_0; // @ 0x814 + union { + uint32_t value; + struct { + uint32_t ef_sw_sf_aes_mode : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t ef_sw_sboot_sign_mode : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t ef_sw_sboot_en : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t ef_sw_cpu1_enc_en : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t ef_sw_cpu0_enc_en : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t pad0 : 4; + uint32_t ef_sw_sw_usage_1 : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t ef_sw_sdu_dis : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t ef_sw_ble_dis : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t ef_sw_wifi_dis : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t ef_sw_0_key_enc_en : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t ef_sw_cam_dis : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t ef_sw_sf_dis : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t ef_sw_cpu1_dis : 1; // @ 20 -- 20 # 0xffefffff + uint32_t ef_sw_cpu_rst_dbg_dis : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t ef_sw_se_dbg_dis : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t ef_sw_efuse_dbg_dis : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t ef_sw_dbg_jtag_1_dis : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t ef_sw_dbg_jtag_0_dis : 2; // @ 27 -- 26 # 0xf3ffffff + uint32_t ef_sw_dbg_mode : 4; // @ 31 -- 28 # 0xfffffff + }; + } ef_sw_cfg_0; // @ 0x818 + union { + uint32_t value; + struct { + uint32_t ef_reserved : 32; // @ 31 -- 0 # 0x0 + }; + } ef_reserved; // @ 0x81c + union { + uint32_t value; + struct { + uint32_t ef_if_ana_trim_0 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_if_ana_trim_0; // @ 0x820 + union { + uint32_t value; + struct { + uint32_t ef_if_sw_usage_0 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_if_sw_usage_0; // @ 0x824 + uint8_t pad1[0x1d8]; + union { + uint32_t value; + struct { + uint32_t ef_crc_busy : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t ef_crc_trig : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t ef_crc_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t ef_crc_mode : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t ef_crc_error : 1; // @ 4 -- 4 # 0xffffffef + uint32_t ef_crc_dout_inv_en : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t ef_crc_dout_endian : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t ef_crc_din_endian : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t ef_crc_int : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t ef_crc_int_clr : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t ef_crc_int_set : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t ef_crc_lock : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t pad0 : 4; + uint32_t ef_crc_slp_n : 16; // @ 31 -- 16 # 0xffff + }; + } ef_crc_ctrl_0; // @ 0xa00 + union { + uint32_t value; + struct { + uint32_t ef_crc_data_0_en : 32; // @ 31 -- 0 # 0x0 + }; + } ef_crc_ctrl_1; // @ 0xa04 + union { + uint32_t value; + struct { + uint32_t ef_crc_data_1_en : 32; // @ 31 -- 0 # 0x0 + }; + } ef_crc_ctrl_2; // @ 0xa08 + union { + uint32_t value; + struct { + uint32_t ef_crc_iv : 32; // @ 31 -- 0 # 0x0 + }; + } ef_crc_ctrl_3; // @ 0xa0c + union { + uint32_t value; + struct { + uint32_t ef_crc_golden : 32; // @ 31 -- 0 # 0x0 + }; + } ef_crc_ctrl_4; // @ 0xa10 + union { + uint32_t value; + struct { + uint32_t ef_crc_dout : 32; // @ 31 -- 0 # 0x0 + }; + } ef_crc_ctrl_5; // @ 0xa14 + }; +} ef_ctrl_regs; +#define EF_CTRL_BASE 0x40007000 +#define EF_CTRL ((ef_ctrl_regs* volatile)(EF_CTRL_BASE)) \ No newline at end of file diff --git a/src/include/soc/ef_data_0.h b/src/include/soc/ef_data_0.h new file mode 100644 index 0000000..612e008 --- /dev/null +++ b/src/include/soc/ef_data_0.h @@ -0,0 +1,238 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + union { + uint32_t value; + struct { + uint32_t ef_sf_aes_mode : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t ef_sboot_sign_mode : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t ef_sboot_en : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t ef_cpu1_enc_en : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t ef_cpu0_enc_en : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t ef_boot_sel : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t ef_sw_usage_1 : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t ef_sdu_dis : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t ef_ble_dis : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t ef_wifi_dis : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t ef_0_key_enc_en : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t ef_cam_dis : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t ef_sf_dis : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t ef_cpu1_dis : 1; // @ 20 -- 20 # 0xffefffff + uint32_t ef_cpu_rst_dbg_dis : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t ef_se_dbg_dis : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t ef_efuse_dbg_dis : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t ef_dbg_jtag_1_dis : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t ef_dbg_jtag_0_dis : 2; // @ 27 -- 26 # 0xf3ffffff + uint32_t ef_dbg_mode : 4; // @ 31 -- 28 # 0xfffffff + }; + } ef_cfg_0; // @ 0x0 + union { + uint32_t value; + struct { + uint32_t ef_dbg_pwd_low : 32; // @ 31 -- 0 # 0x0 + }; + } ef_dbg_pwd_low; // @ 0x4 + union { + uint32_t value; + struct { + uint32_t ef_dbg_pwd_high : 32; // @ 31 -- 0 # 0x0 + }; + } ef_dbg_pwd_high; // @ 0x8 + union { + uint32_t value; + struct { + uint32_t ef_ana_trim_0 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_ana_trim_0; // @ 0xc + union { + uint32_t value; + struct { + uint32_t ef_sw_usage_0 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_sw_usage_0; // @ 0x10 + union { + uint32_t value; + struct { + uint32_t ef_wifi_mac_low : 32; // @ 31 -- 0 # 0x0 + }; + } ef_wifi_mac_low; // @ 0x14 + union { + uint32_t value; + struct { + uint32_t ef_wifi_mac_high : 32; // @ 31 -- 0 # 0x0 + }; + } ef_wifi_mac_high; // @ 0x18 + union { + uint32_t value; + struct { + uint32_t ef_key_slot_0_w0 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_0_w0; // @ 0x1c + union { + uint32_t value; + struct { + uint32_t ef_key_slot_0_w1 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_0_w1; // @ 0x20 + union { + uint32_t value; + struct { + uint32_t ef_key_slot_0_w2 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_0_w2; // @ 0x24 + union { + uint32_t value; + struct { + uint32_t ef_key_slot_0_w3 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_0_w3; // @ 0x28 + union { + uint32_t value; + struct { + uint32_t ef_key_slot_1_w0 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_1_w0; // @ 0x2c + union { + uint32_t value; + struct { + uint32_t ef_key_slot_1_w1 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_1_w1; // @ 0x30 + union { + uint32_t value; + struct { + uint32_t ef_key_slot_1_w2 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_1_w2; // @ 0x34 + union { + uint32_t value; + struct { + uint32_t ef_key_slot_1_w3 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_1_w3; // @ 0x38 + union { + uint32_t value; + struct { + uint32_t ef_key_slot_2_w0 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_2_w0; // @ 0x3c + union { + uint32_t value; + struct { + uint32_t ef_key_slot_2_w1 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_2_w1; // @ 0x40 + union { + uint32_t value; + struct { + uint32_t ef_key_slot_2_w2 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_2_w2; // @ 0x44 + union { + uint32_t value; + struct { + uint32_t ef_key_slot_2_w3 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_2_w3; // @ 0x48 + union { + uint32_t value; + struct { + uint32_t ef_key_slot_3_w0 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_3_w0; // @ 0x4c + union { + uint32_t value; + struct { + uint32_t ef_key_slot_3_w1 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_3_w1; // @ 0x50 + union { + uint32_t value; + struct { + uint32_t ef_key_slot_3_w2 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_3_w2; // @ 0x54 + union { + uint32_t value; + struct { + uint32_t ef_key_slot_3_w3 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_3_w3; // @ 0x58 + union { + uint32_t value; + struct { + uint32_t ef_key_slot_4_w0 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_4_w0; // @ 0x5c + union { + uint32_t value; + struct { + uint32_t ef_key_slot_4_w1 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_4_w1; // @ 0x60 + union { + uint32_t value; + struct { + uint32_t ef_key_slot_4_w2 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_4_w2; // @ 0x64 + union { + uint32_t value; + struct { + uint32_t ef_key_slot_4_w3 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_4_w3; // @ 0x68 + union { + uint32_t value; + struct { + uint32_t ef_key_slot_5_w0 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_5_w0; // @ 0x6c + union { + uint32_t value; + struct { + uint32_t ef_key_slot_5_w1 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_5_w1; // @ 0x70 + union { + uint32_t value; + struct { + uint32_t ef_key_slot_5_w2 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_5_w2; // @ 0x74 + union { + uint32_t value; + struct { + uint32_t ef_key_slot_5_w3 : 32; // @ 31 -- 0 # 0x0 + }; + } ef_key_slot_5_w3; // @ 0x78 + union { + uint32_t value; + struct { + uint32_t ef_ana_trim_1 : 13; // @ 12 -- 0 # 0xffffe000 + uint32_t wr_lock_key_slot_4_l : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t wr_lock_key_slot_5_l : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t wr_lock_boot_mode : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t wr_lock_dbg_pwd : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t wr_lock_sw_usage_0 : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t wr_lock_wifi_mac : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t wr_lock_key_slot_0 : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t wr_lock_key_slot_1 : 1; // @ 20 -- 20 # 0xffefffff + uint32_t wr_lock_key_slot_2 : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t wr_lock_key_slot_3 : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t wr_lock_key_slot_4_h : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t wr_lock_key_slot_5_h : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t rd_lock_dbg_pwd : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t rd_lock_key_slot_0 : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t rd_lock_key_slot_1 : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t rd_lock_key_slot_2 : 1; // @ 28 -- 28 # 0xefffffff + uint32_t rd_lock_key_slot_3 : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t rd_lock_key_slot_4 : 1; // @ 30 -- 30 # 0xbfffffff + uint32_t rd_lock_key_slot_5 : 1; // @ 31 -- 31 # 0x7fffffff + }; + } ef_data_0_lock; // @ 0x7c + }; +} ef_data_0_regs; +#define EF_DATA_0_BASE 0x40007000 +#define EF_DATA_0 ((ef_data_0_regs* volatile)(EF_DATA_0_BASE)) \ No newline at end of file diff --git a/src/include/soc/ef_data_1.h b/src/include/soc/ef_data_1.h new file mode 100644 index 0000000..3667e6a --- /dev/null +++ b/src/include/soc/ef_data_1.h @@ -0,0 +1,130 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + uint8_t pad0[0x80]; + union { + uint32_t value; + struct { + uint32_t reg_key_slot_6_w0 : 32; // @ 31 -- 0 # 0x0 + }; + } reg_key_slot_6_w0; // @ 0x80 + union { + uint32_t value; + struct { + uint32_t reg_key_slot_6_w1 : 32; // @ 31 -- 0 # 0x0 + }; + } reg_key_slot_6_w1; // @ 0x84 + union { + uint32_t value; + struct { + uint32_t reg_key_slot_6_w2 : 32; // @ 31 -- 0 # 0x0 + }; + } reg_key_slot_6_w2; // @ 0x88 + union { + uint32_t value; + struct { + uint32_t reg_key_slot_6_w3 : 32; // @ 31 -- 0 # 0x0 + }; + } reg_key_slot_6_w3; // @ 0x8c + union { + uint32_t value; + struct { + uint32_t reg_key_slot_7_w0 : 32; // @ 31 -- 0 # 0x0 + }; + } reg_key_slot_7_w0; // @ 0x90 + union { + uint32_t value; + struct { + uint32_t reg_key_slot_7_w1 : 32; // @ 31 -- 0 # 0x0 + }; + } reg_key_slot_7_w1; // @ 0x94 + union { + uint32_t value; + struct { + uint32_t reg_key_slot_7_w2 : 32; // @ 31 -- 0 # 0x0 + }; + } reg_key_slot_7_w2; // @ 0x98 + union { + uint32_t value; + struct { + uint32_t reg_key_slot_7_w3 : 32; // @ 31 -- 0 # 0x0 + }; + } reg_key_slot_7_w3; // @ 0x9c + union { + uint32_t value; + struct { + uint32_t reg_key_slot_8_w0 : 32; // @ 31 -- 0 # 0x0 + }; + } reg_key_slot_8_w0; // @ 0xa0 + union { + uint32_t value; + struct { + uint32_t reg_key_slot_8_w1 : 32; // @ 31 -- 0 # 0x0 + }; + } reg_key_slot_8_w1; // @ 0xa4 + union { + uint32_t value; + struct { + uint32_t reg_key_slot_8_w2 : 32; // @ 31 -- 0 # 0x0 + }; + } reg_key_slot_8_w2; // @ 0xa8 + union { + uint32_t value; + struct { + uint32_t reg_key_slot_8_w3 : 32; // @ 31 -- 0 # 0x0 + }; + } reg_key_slot_8_w3; // @ 0xac + union { + uint32_t value; + struct { + uint32_t reg_key_slot_9_w0 : 32; // @ 31 -- 0 # 0x0 + }; + } reg_key_slot_9_w0; // @ 0xb0 + union { + uint32_t value; + struct { + uint32_t reg_key_slot_9_w1 : 32; // @ 31 -- 0 # 0x0 + }; + } reg_key_slot_9_w1; // @ 0xb4 + union { + uint32_t value; + struct { + uint32_t reg_key_slot_9_w2 : 32; // @ 31 -- 0 # 0x0 + }; + } reg_key_slot_9_w2; // @ 0xb8 + union { + uint32_t value; + struct { + uint32_t reg_key_slot_9_w3 : 32; // @ 31 -- 0 # 0x0 + }; + } reg_key_slot_9_w3; // @ 0xbc + uint32_t reg_key_slot_10_w0; // @ 0xc0 + uint32_t reg_key_slot_10_w1; // @ 0xc4 + uint32_t reg_key_slot_10_w2; // @ 0xc8 + uint32_t reg_key_slot_10_w3; // @ 0xcc + uint32_t reg_key_slot_11_w0; // @ 0xd0 + uint32_t reg_key_slot_11_w1; // @ 0xd4 + uint32_t reg_key_slot_11_w2; // @ 0xd8 + uint32_t reg_key_slot_11_w3; // @ 0xdc + union { + uint32_t value; + struct { + uint32_t RESERVED_9_0 : 10; // @ 9 -- 0 # 0xfffffc00 + uint32_t wr_lock_key_slot_6 : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t wr_lock_key_slot_7 : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t wr_lock_key_slot_8 : 1; // @ 12 -- 12 # 0xffffefff + uint32_t wr_lock_key_slot_9 : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t pad0 : 2; + uint32_t RESERVED_25_16 : 10; // @ 25 -- 16 # 0xfc00ffff + uint32_t rd_lock_key_slot_6 : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t rd_lock_key_slot_7 : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t rd_lock_key_slot_8 : 1; // @ 28 -- 28 # 0xefffffff + uint32_t rd_lock_key_slot_9 : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t pad1 : 2; + }; + } reg_data_1_lock; // @ 0xe0 + }; +} ef_data_1_regs; +#define EF_DATA_1_BASE 0x40007000 +#define EF_DATA_1 ((ef_data_1_regs* volatile)(EF_DATA_1_BASE)) \ No newline at end of file diff --git a/src/include/soc/gpip.h b/src/include/soc/gpip.h new file mode 100644 index 0000000..ae4f5a4 --- /dev/null +++ b/src/include/soc/gpip.h @@ -0,0 +1,82 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + union { + uint32_t value; + struct { + uint32_t gpadc_dma_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t gpadc_fifo_clr : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t gpadc_fifo_ne : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t gpadc_fifo_full : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t gpadc_rdy : 1; // @ 4 -- 4 # 0xffffffef + uint32_t gpadc_fifo_overrun : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t gpadc_fifo_underrun : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t pad0 : 1; + uint32_t gpadc_rdy_clr : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t gpadc_fifo_overrun_clr : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t gpadc_fifo_underrun_clr : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t pad1 : 1; + uint32_t gpadc_rdy_mask : 1; // @ 12 -- 12 # 0xffffefff + uint32_t gpadc_fifo_overrun_mask : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t gpadc_fifo_underrun_mask : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t pad2 : 1; + uint32_t gpadc_fifo_data_count : 6; // @ 21 -- 16 # 0xffc0ffff + uint32_t gpadc_fifo_thl : 2; // @ 23 -- 22 # 0xff3fffff + uint32_t rsvd_31_24 : 8; // @ 31 -- 24 # 0xffffff + }; + } gpadc_config; // @ 0x0 + union { + uint32_t value; + struct { + uint32_t gpadc_dma_rdata : 26; // @ 25 -- 0 # 0xfc000000 + uint32_t rsvd_31_26 : 6; // @ 31 -- 26 # 0x3ffffff + }; + } gpadc_dma_rdata; // @ 0x4 + uint8_t pad0[0x38]; + union { + uint32_t value; + struct { + uint32_t gpdac_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t gpdac_en2 : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t pad0 : 2; + uint32_t dsm_mode : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t pad1 : 2; + uint32_t gpdac_mode : 3; // @ 10 -- 8 # 0xfffff8ff + uint32_t pad2 : 5; + uint32_t gpdac_ch_a_sel : 4; // @ 19 -- 16 # 0xfff0ffff + uint32_t gpdac_ch_b_sel : 4; // @ 23 -- 20 # 0xff0fffff + uint32_t rsvd_31_24 : 8; // @ 31 -- 24 # 0xffffff + }; + } gpdac_config; // @ 0x40 + union { + uint32_t value; + struct { + uint32_t gpdac_dma_tx_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 3; + uint32_t gpdac_dma_format : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t pad1 : 26; + }; + } gpdac_dma_config; // @ 0x44 + union { + uint32_t value; + struct { + uint32_t gpdac_dma_wdata : 32; // @ 31 -- 0 # 0x0 + }; + } gpdac_dma_wdata; // @ 0x48 + union { + uint32_t value; + struct { + uint32_t tx_fifo_empty : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t tx_fifo_full : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t tx_cs : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t TxFifoRdPtr : 3; // @ 6 -- 4 # 0xffffff8f + uint32_t pad0 : 1; + uint32_t TxFifoWrPtr : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad1 : 22; + }; + } gpdac_tx_fifo_status; // @ 0x4c + }; +} gpip_regs; +#define GPIP_BASE 0x40002000 +#define GPIP ((gpip_regs* volatile)(GPIP_BASE)) \ No newline at end of file diff --git a/src/include/soc/i2c.h b/src/include/soc/i2c.h new file mode 100644 index 0000000..805c66b --- /dev/null +++ b/src/include/soc/i2c.h @@ -0,0 +1,142 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + union { + uint32_t value; + struct { + uint32_t cr_i2c_m_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t cr_i2c_pkt_dir : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t cr_i2c_deg_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t cr_i2c_scl_sync_en : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t cr_i2c_sub_addr_en : 1; // @ 4 -- 4 # 0xffffffef + uint32_t cr_i2c_sub_addr_bc : 2; // @ 6 -- 5 # 0xffffff9f + uint32_t pad0 : 1; + uint32_t cr_i2c_slv_addr : 7; // @ 14 -- 8 # 0xffff80ff + uint32_t pad1 : 1; + uint32_t cr_i2c_pkt_len : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t pad2 : 4; + uint32_t cr_i2c_deg_cnt : 4; // @ 31 -- 28 # 0xfffffff + }; + } i2c_config; // @ 0x0 + union { + uint32_t value; + struct { + uint32_t i2c_end_int : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t i2c_txf_int : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t i2c_rxf_int : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t i2c_nak_int : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t i2c_arb_int : 1; // @ 4 -- 4 # 0xffffffef + uint32_t i2c_fer_int : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad0 : 2; + uint32_t cr_i2c_end_mask : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t cr_i2c_txf_mask : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t cr_i2c_rxf_mask : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t cr_i2c_nak_mask : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t cr_i2c_arb_mask : 1; // @ 12 -- 12 # 0xffffefff + uint32_t cr_i2c_fer_mask : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t pad1 : 2; + uint32_t cr_i2c_end_clr : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t rsvd_17 : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t rsvd_18 : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t cr_i2c_nak_clr : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t cr_i2c_arb_clr : 1; // @ 20 -- 20 # 0xffefffff + uint32_t rsvd_21 : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t pad2 : 2; + uint32_t cr_i2c_end_en : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t cr_i2c_txf_en : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t cr_i2c_rxf_en : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t cr_i2c_nak_en : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t cr_i2c_arb_en : 1; // @ 28 -- 28 # 0xefffffff + uint32_t cr_i2c_fer_en : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t pad3 : 2; + }; + } i2c_int_sts; // @ 0x4 + union { + uint32_t value; + struct { + uint32_t cr_i2c_sub_addr_b0 : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t cr_i2c_sub_addr_b1 : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t cr_i2c_sub_addr_b2 : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t cr_i2c_sub_addr_b3 : 8; // @ 31 -- 24 # 0xffffff + }; + } i2c_sub_addr; // @ 0x8 + union { + uint32_t value; + struct { + uint32_t sts_i2c_bus_busy : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t cr_i2c_bus_busy_clr : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t pad0 : 30; + }; + } i2c_bus_busy; // @ 0xc + union { + uint32_t value; + struct { + uint32_t cr_i2c_prd_s_ph_0 : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t cr_i2c_prd_s_ph_1 : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t cr_i2c_prd_s_ph_2 : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t cr_i2c_prd_s_ph_3 : 8; // @ 31 -- 24 # 0xffffff + }; + } i2c_prd_start; // @ 0x10 + union { + uint32_t value; + struct { + uint32_t cr_i2c_prd_p_ph_0 : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t cr_i2c_prd_p_ph_1 : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t cr_i2c_prd_p_ph_2 : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t cr_i2c_prd_p_ph_3 : 8; // @ 31 -- 24 # 0xffffff + }; + } i2c_prd_stop; // @ 0x14 + union { + uint32_t value; + struct { + uint32_t cr_i2c_prd_d_ph_0 : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t cr_i2c_prd_d_ph_1 : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t cr_i2c_prd_d_ph_2 : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t cr_i2c_prd_d_ph_3 : 8; // @ 31 -- 24 # 0xffffff + }; + } i2c_prd_data; // @ 0x18 + uint8_t pad0[0x64]; + union { + uint32_t value; + struct { + uint32_t i2c_dma_tx_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t i2c_dma_rx_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t tx_fifo_clr : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t rx_fifo_clr : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t tx_fifo_overflow : 1; // @ 4 -- 4 # 0xffffffef + uint32_t tx_fifo_underflow : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t rx_fifo_overflow : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t rx_fifo_underflow : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t pad0 : 24; + }; + } i2c_fifo_config_0; // @ 0x80 + union { + uint32_t value; + struct { + uint32_t tx_fifo_cnt : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 6; + uint32_t rx_fifo_cnt : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad1 : 6; + uint32_t tx_fifo_th : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad2 : 7; + uint32_t rx_fifo_th : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t pad3 : 7; + }; + } i2c_fifo_config_1; // @ 0x84 + union { + uint32_t value; + struct { + uint32_t i2c_fifo_wdata : 32; // @ 31 -- 0 # 0x0 + }; + } i2c_fifo_wdata; // @ 0x88 + union { + uint32_t value; + struct { + uint32_t i2c_fifo_rdata : 32; // @ 31 -- 0 # 0x0 + }; + } i2c_fifo_rdata; // @ 0x8c + }; +} i2c_regs; +#define I2C_BASE 0x4000a300 +#define I2C ((i2c_regs* volatile)(I2C_BASE)) \ No newline at end of file diff --git a/src/include/soc/ir.h b/src/include/soc/ir.h new file mode 100644 index 0000000..c1b3a7f --- /dev/null +++ b/src/include/soc/ir.h @@ -0,0 +1,195 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + union { + uint32_t value; + struct { + uint32_t cr_irtx_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t cr_irtx_out_inv : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t cr_irtx_mod_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t cr_irtx_swm_en : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t cr_irtx_data_en : 1; // @ 4 -- 4 # 0xffffffef + uint32_t cr_irtx_logic0_hl_inv : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t cr_irtx_logic1_hl_inv : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t pad0 : 1; + uint32_t cr_irtx_head_en : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t cr_irtx_head_hl_inv : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t cr_irtx_tail_en : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t cr_irtx_tail_hl_inv : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t cr_irtx_data_num : 6; // @ 17 -- 12 # 0xfffc0fff + uint32_t pad1 : 14; + }; + } irtx_config; // @ 0x0 + union { + uint32_t value; + struct { + uint32_t irtx_end_int : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 7; + uint32_t cr_irtx_end_mask : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pad1 : 7; + uint32_t cr_irtx_end_clr : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad2 : 7; + uint32_t cr_irtx_end_en : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t pad3 : 7; + }; + } irtx_int_sts; // @ 0x4 + union { + uint32_t value; + struct { + uint32_t cr_irtx_data_word0 : 32; // @ 31 -- 0 # 0x0 + }; + } irtx_data_word0; // @ 0x8 + union { + uint32_t value; + struct { + uint32_t cr_irtx_data_word1 : 32; // @ 31 -- 0 # 0x0 + }; + } irtx_data_word1; // @ 0xc + union { + uint32_t value; + struct { + uint32_t cr_irtx_pw_unit : 12; // @ 11 -- 0 # 0xfffff000 + uint32_t pad0 : 4; + uint32_t cr_irtx_mod_ph0_w : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t cr_irtx_mod_ph1_w : 8; // @ 31 -- 24 # 0xffffff + }; + } irtx_pulse_width; // @ 0x10 + union { + uint32_t value; + struct { + uint32_t cr_irtx_logic0_ph0_w : 4; // @ 3 -- 0 # 0xfffffff0 + uint32_t cr_irtx_logic0_ph1_w : 4; // @ 7 -- 4 # 0xffffff0f + uint32_t cr_irtx_logic1_ph0_w : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t cr_irtx_logic1_ph1_w : 4; // @ 15 -- 12 # 0xffff0fff + uint32_t cr_irtx_head_ph0_w : 4; // @ 19 -- 16 # 0xfff0ffff + uint32_t cr_irtx_head_ph1_w : 4; // @ 23 -- 20 # 0xff0fffff + uint32_t cr_irtx_tail_ph0_w : 4; // @ 27 -- 24 # 0xf0ffffff + uint32_t cr_irtx_tail_ph1_w : 4; // @ 31 -- 28 # 0xfffffff + }; + } irtx_pw; // @ 0x14 + uint8_t pad0[0x28]; + union { + uint32_t value; + struct { + uint32_t cr_irtx_swm_pw_0 : 32; // @ 31 -- 0 # 0x0 + }; + } irtx_swm_pw_0; // @ 0x40 + union { + uint32_t value; + struct { + uint32_t cr_irtx_swm_pw_1 : 32; // @ 31 -- 0 # 0x0 + }; + } irtx_swm_pw_1; // @ 0x44 + union { + uint32_t value; + struct { + uint32_t cr_irtx_swm_pw_2 : 32; // @ 31 -- 0 # 0x0 + }; + } irtx_swm_pw_2; // @ 0x48 + union { + uint32_t value; + struct { + uint32_t cr_irtx_swm_pw_3 : 32; // @ 31 -- 0 # 0x0 + }; + } irtx_swm_pw_3; // @ 0x4c + union { + uint32_t value; + struct { + uint32_t cr_irtx_swm_pw_4 : 32; // @ 31 -- 0 # 0x0 + }; + } irtx_swm_pw_4; // @ 0x50 + union { + uint32_t value; + struct { + uint32_t cr_irtx_swm_pw_5 : 32; // @ 31 -- 0 # 0x0 + }; + } irtx_swm_pw_5; // @ 0x54 + union { + uint32_t value; + struct { + uint32_t cr_irtx_swm_pw_6 : 32; // @ 31 -- 0 # 0x0 + }; + } irtx_swm_pw_6; // @ 0x58 + union { + uint32_t value; + struct { + uint32_t cr_irtx_swm_pw_7 : 32; // @ 31 -- 0 # 0x0 + }; + } irtx_swm_pw_7; // @ 0x5c + uint8_t pad1[0x20]; + union { + uint32_t value; + struct { + uint32_t cr_irrx_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t cr_irrx_in_inv : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t cr_irrx_mode : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t cr_irrx_deg_en : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pad0 : 3; + uint32_t cr_irrx_deg_cnt : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t pad1 : 20; + }; + } irrx_config; // @ 0x80 + union { + uint32_t value; + struct { + uint32_t irrx_end_int : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 7; + uint32_t cr_irrx_end_mask : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pad1 : 7; + uint32_t cr_irrx_end_clr : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad2 : 7; + uint32_t cr_irrx_end_en : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t pad3 : 7; + }; + } irrx_int_sts; // @ 0x84 + union { + uint32_t value; + struct { + uint32_t cr_irrx_data_th : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t cr_irrx_end_th : 16; // @ 31 -- 16 # 0xffff + }; + } irrx_pw_config; // @ 0x88 + uint8_t pad2[0x4]; + union { + uint32_t value; + struct { + uint32_t sts_irrx_data_cnt : 7; // @ 6 -- 0 # 0xffffff80 + uint32_t pad0 : 25; + }; + } irrx_data_count; // @ 0x90 + union { + uint32_t value; + struct { + uint32_t sts_irrx_data_word0 : 32; // @ 31 -- 0 # 0x0 + }; + } irrx_data_word0; // @ 0x94 + union { + uint32_t value; + struct { + uint32_t sts_irrx_data_word1 : 32; // @ 31 -- 0 # 0x0 + }; + } irrx_data_word1; // @ 0x98 + uint8_t pad3[0x24]; + union { + uint32_t value; + struct { + uint32_t rx_fifo_clr : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 1; + uint32_t rx_fifo_overflow : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t rx_fifo_underflow : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t rx_fifo_cnt : 7; // @ 10 -- 4 # 0xfffff80f + uint32_t pad1 : 21; + }; + } irrx_swm_fifo_config_0; // @ 0xc0 + union { + uint32_t value; + struct { + uint32_t rx_fifo_rdata : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } irrx_swm_fifo_rdata; // @ 0xc4 + }; +} ir_regs; +#define IR_BASE 0x4000a600 +#define IR ((ir_regs* volatile)(IR_BASE)) \ No newline at end of file diff --git a/src/include/soc/l1c.h b/src/include/soc/l1c.h new file mode 100644 index 0000000..ce77cad --- /dev/null +++ b/src/include/soc/l1c.h @@ -0,0 +1,84 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + union { + uint32_t value; + struct { + uint32_t l1c_cacheable : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t l1c_cnt_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t l1c_invalid_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t l1c_invalid_done : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pad0 : 4; + uint32_t l1c_way_dis : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t irom_2t_access : 1; // @ 12 -- 12 # 0xffffefff + uint32_t pad1 : 1; + uint32_t l1c_bypass : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t l1c_bmx_err_en : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t l1c_bmx_arb_mode : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad2 : 2; + uint32_t l1c_bmx_timeout_en : 4; // @ 23 -- 20 # 0xff0fffff + uint32_t l1c_bmx_busy_option_dis : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t early_resp_dis : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t wrap_dis : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t pad3 : 5; + }; + } l1c_config; // @ 0x0 + union { + uint32_t value; + struct { + uint32_t hit_cnt_lsb : 32; // @ 31 -- 0 # 0x0 + }; + } hit_cnt_lsb; // @ 0x4 + union { + uint32_t value; + struct { + uint32_t hit_cnt_msb : 32; // @ 31 -- 0 # 0x0 + }; + } hit_cnt_msb; // @ 0x8 + union { + uint32_t value; + struct { + uint32_t miss_cnt : 32; // @ 31 -- 0 # 0x0 + }; + } miss_cnt; // @ 0xc + uint32_t l1c_range; // @ 0x10 + uint8_t pad0[0x1ec]; + union { + uint32_t value; + struct { + uint32_t l1c_bmx_err_addr_dis : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 3; + uint32_t l1c_bmx_err_dec : 1; // @ 4 -- 4 # 0xffffffef + uint32_t l1c_bmx_err_tz : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad1 : 10; + uint32_t l1c_hsel_option : 4; // @ 19 -- 16 # 0xfff0ffff + uint32_t pad2 : 12; + }; + } l1c_bmx_err_addr_en; // @ 0x200 + union { + uint32_t value; + struct { + uint32_t l1c_bmx_err_addr : 32; // @ 31 -- 0 # 0x0 + }; + } l1c_bmx_err_addr; // @ 0x204 + union { + uint32_t value; + struct { + uint32_t irom1_misr_dataout_0 : 32; // @ 31 -- 0 # 0x0 + }; + } irom1_misr_dataout_0; // @ 0x208 + uint32_t irom1_misr_dataout_1; // @ 0x20c + union { + uint32_t value; + struct { + uint32_t force_e21_clock_on_0 : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t force_e21_clock_on_1 : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t force_e21_clock_on_2 : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 29; + }; + } cpu_clk_gate; // @ 0x210 + }; +} l1c_regs; +#define L1C_BASE 0x40009000 +#define L1C ((l1c_regs* volatile)(L1C_BASE)) \ No newline at end of file diff --git a/src/include/soc/pds.h b/src/include/soc/pds.h new file mode 100644 index 0000000..c0e6079 --- /dev/null +++ b/src/include/soc/pds.h @@ -0,0 +1,284 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + union { + uint32_t value; + struct { + uint32_t pds_start_ps : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t cr_sleep_forever : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t cr_xtal_force_off : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t cr_wifi_pds_save_state : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t cr_pds_pd_dcdc18 : 1; // @ 4 -- 4 # 0xffffffef + uint32_t cr_pds_pd_bg_sys : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad0 : 2; + uint32_t cr_pds_gate_clk : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t cr_pds_mem_stby : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t pad1 : 1; + uint32_t cr_pds_iso_en : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t cr_pds_wait_xtal_rdy : 1; // @ 12 -- 12 # 0xffffefff + uint32_t cr_pds_pwr_off : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t cr_pds_pd_xtal : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t cr_pds_soc_enb_force_on : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t cr_pds_rst_soc_en : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t cr_pds_rc32m_off_dis : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t cr_pds_ldo_vsel_en : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t pad2 : 2; + uint32_t cr_np_wfi_mask : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t cr_pds_pd_ldo11 : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t pad3 : 1; + uint32_t cr_pds_ldo_vol : 4; // @ 27 -- 24 # 0xf0ffffff + uint32_t cr_pds_ctrl_rf : 2; // @ 29 -- 28 # 0xcfffffff + uint32_t cr_pds_ctrl_pll : 2; // @ 31 -- 30 # 0x3fffffff + }; + } PDS_CTL; // @ 0x0 + union { + uint32_t value; + struct { + uint32_t cr_sleep_duration : 32; // @ 31 -- 0 # 0x0 + }; + } PDS_TIME1; // @ 0x4 + uint8_t pad0[0x4]; + union { + uint32_t value; + struct { + uint32_t ro_pds_wake_int : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t ro_pds_irq_in : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t ro_pds_rf_done_int : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t ro_pds_pll_done_int : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pad0 : 4; + uint32_t cr_pds_wake_int_mask : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t cr_pds_irq_in_dis : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t cr_pds_rf_done_int_mask : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t cr_pds_pll_done_int_mask : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t pad1 : 4; + uint32_t cr_pds_int_clr : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad2 : 15; + }; + } PDS_INT; // @ 0xc + union { + uint32_t value; + struct { + uint32_t cr_pds_force_np_pwr_off : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 1; + uint32_t cr_pds_force_wb_pwr_off : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad1 : 1; + uint32_t cr_pds_force_np_iso_en : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pad2 : 1; + uint32_t cr_pds_force_wb_iso_en : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t pad3 : 1; + uint32_t cr_pds_force_np_pds_rst : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pad4 : 1; + uint32_t cr_pds_force_wb_pds_rst : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t pad5 : 1; + uint32_t cr_pds_force_np_mem_stby : 1; // @ 12 -- 12 # 0xffffefff + uint32_t pad6 : 1; + uint32_t cr_pds_force_wb_mem_stby : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t pad7 : 1; + uint32_t cr_pds_force_np_gate_clk : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad8 : 1; + uint32_t cr_pds_force_wb_gate_clk : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t pad9 : 13; + }; + } PDS_CTL2; // @ 0x10 + union { + uint32_t value; + struct { + uint32_t pad0 : 1; + uint32_t cr_pds_force_misc_pwr_off : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t pad1 : 2; + uint32_t cr_pds_force_misc_iso_en : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pad2 : 2; + uint32_t cr_pds_force_misc_pds_rst : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t pad3 : 2; + uint32_t cr_pds_force_misc_mem_stby : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t pad4 : 2; + uint32_t cr_pds_force_misc_gate_clk : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t pad5 : 10; + uint32_t cr_pds_np_iso_en : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t pad6 : 2; + uint32_t cr_pds_wb_iso_en : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t pad7 : 2; + uint32_t cr_pds_misc_iso_en : 1; // @ 30 -- 30 # 0xbfffffff + uint32_t pad8 : 1; + }; + } PDS_CTL3; // @ 0x14 + union { + uint32_t value; + struct { + uint32_t cr_pds_np_pwr_off : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t cr_pds_np_reset : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t cr_pds_np_mem_stby : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t cr_pds_np_gate_clk : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pad0 : 8; + uint32_t cr_pds_wb_pwr_off : 1; // @ 12 -- 12 # 0xffffefff + uint32_t cr_pds_wb_reset : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t cr_pds_wb_mem_stby : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t cr_pds_wb_gate_clk : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t pad1 : 8; + uint32_t cr_pds_misc_pwr_off : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t cr_pds_misc_reset : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t cr_pds_misc_mem_stby : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t cr_pds_misc_gate_clk : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t pad2 : 4; + }; + } PDS_CTL4; // @ 0x18 + union { + uint32_t value; + struct { + uint32_t ro_pds_state : 4; // @ 3 -- 0 # 0xfffffff0 + uint32_t pad0 : 4; + uint32_t ro_pds_rf_state : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t pad1 : 4; + uint32_t ro_pds_pll_state : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad2 : 14; + }; + } pds_stat; // @ 0x1c + union { + uint32_t value; + struct { + uint32_t cr_np_sram_pwr : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pad0 : 24; + }; + } pds_ram1; // @ 0x20 + uint8_t pad1[0x2dc]; + union { + uint32_t value; + struct { + uint32_t rc32m_cal_done : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t rc32m_rdy : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t rc32m_cal_inprogress : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t rc32m_cal_div : 2; // @ 4 -- 3 # 0xffffffe7 + uint32_t rc32m_cal_precharge : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t rc32m_dig_code_fr_cal : 8; // @ 13 -- 6 # 0xffffc03f + uint32_t pad0 : 3; + uint32_t rc32m_allow_cal : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t rc32m_refclk_half : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t rc32m_ext_code_en : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t rc32m_cal_en : 1; // @ 20 -- 20 # 0xffefffff + uint32_t rc32m_pd : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t rc32m_code_fr_ext : 8; // @ 29 -- 22 # 0xc03fffff + uint32_t pad1 : 2; + }; + } rc32m_ctrl0; // @ 0x300 + union { + uint32_t value; + struct { + uint32_t rc32m_test_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t rc32m_soft_rst : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t rc32m_clk_soft_rst : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t rc32m_clk_inv : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t rc32m_clk_force_on : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pad0 : 19; + uint32_t rc32m_reserved : 8; // @ 31 -- 24 # 0xffffff + }; + } rc32m_ctrl1; // @ 0x304 + uint8_t pad2[0xf8]; + union { + uint32_t value; + struct { + uint32_t clkpll_sdm_reset : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t clkpll_reset_postdiv : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t clkpll_reset_fbdv : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t clkpll_reset_refdiv : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t clkpll_pu_postdiv : 1; // @ 4 -- 4 # 0xffffffef + uint32_t clkpll_pu_fbdv : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t clkpll_pu_clamp_op : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t clkpll_pu_pfd : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t clkpll_pu_cp : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pu_clkpll_sfreg : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t pu_clkpll : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t pad0 : 21; + }; + } pu_rst_clkpll; // @ 0x400 + union { + uint32_t value; + struct { + uint32_t clkpll_postdiv : 7; // @ 6 -- 0 # 0xffffff80 + uint32_t pad0 : 1; + uint32_t clkpll_refdiv_ratio : 4; // @ 11 -- 8 # 0xfffff0ff + uint32_t clkpll_xtal_rc32m_sel : 1; // @ 12 -- 12 # 0xffffefff + uint32_t pad1 : 3; + uint32_t clkpll_refclk_sel : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad2 : 3; + uint32_t clkpll_vg11_sel : 2; // @ 21 -- 20 # 0xffcfffff + uint32_t pad3 : 2; + uint32_t clkpll_vg13_sel : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t pad4 : 6; + }; + } clkpll_top_ctrl; // @ 0x404 + union { + uint32_t value; + struct { + uint32_t clkpll_sel_cp_bias : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 3; + uint32_t clkpll_icp_5u : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t clkpll_icp_1u : 2; // @ 7 -- 6 # 0xffffff3f + uint32_t clkpll_int_frac_sw : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t clkpll_cp_startup_en : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t clkpll_cp_opamp_en : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t pad1 : 21; + }; + } clkpll_cp; // @ 0x408 + union { + uint32_t value; + struct { + uint32_t clkpll_c4_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 3; + uint32_t clkpll_r4 : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t pad1 : 2; + uint32_t clkpll_r4_short : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t pad2 : 3; + uint32_t clkpll_c3 : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t clkpll_cz : 2; // @ 15 -- 14 # 0xffff3fff + uint32_t clkpll_rz : 3; // @ 18 -- 16 # 0xfff8ffff + uint32_t pad3 : 13; + }; + } clkpll_rz; // @ 0x40c + union { + uint32_t value; + struct { + uint32_t clkpll_sel_sample_clk : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t clkpll_sel_fb_clk : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t pad0 : 28; + }; + } clkpll_fbdv; // @ 0x410 + union { + uint32_t value; + struct { + uint32_t clkpll_vco_speed : 3; // @ 2 -- 0 # 0xfffffff8 + uint32_t clkpll_shrtr : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pad0 : 28; + }; + } clkpll_vco; // @ 0x414 + union { + uint32_t value; + struct { + uint32_t clkpll_sdmin : 24; // @ 23 -- 0 # 0xff000000 + uint32_t clkpll_dither_sel : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t pad0 : 2; + uint32_t clkpll_sdm_flag : 1; // @ 28 -- 28 # 0xefffffff + uint32_t clkpll_sdm_bypass : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t pad1 : 2; + }; + } clkpll_sdm; // @ 0x418 + union { + uint32_t value; + struct { + uint32_t clkpll_en_480m : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t clkpll_en_240m : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t clkpll_en_192m : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t clkpll_en_160m : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t clkpll_en_120m : 1; // @ 4 -- 4 # 0xffffffef + uint32_t clkpll_en_96m : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t clkpll_en_80m : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t clkpll_en_48m : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t clkpll_en_32m : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t clkpll_en_div2_480m : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t pad0 : 22; + }; + } clkpll_output_en; // @ 0x41c + }; +} pds_regs; +#define PDS_BASE 0x4000e000 +#define PDS ((pds_regs* volatile)(PDS_BASE)) \ No newline at end of file diff --git a/src/include/soc/pwm.h b/src/include/soc/pwm.h new file mode 100644 index 0000000..14c358d --- /dev/null +++ b/src/include/soc/pwm.h @@ -0,0 +1,267 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + union { + uint32_t value; + struct { + uint32_t pwm_interrupt_sts : 6; // @ 5 -- 0 # 0xffffffc0 + uint32_t pad0 : 2; + uint32_t pwm_int_clear : 6; // @ 13 -- 8 # 0xffffc0ff + uint32_t pad1 : 18; + }; + } pwm_int_config; // @ 0x0 + uint8_t pad0[0x1c]; + union { + uint32_t value; + struct { + uint32_t pwm_clk_div : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } pwm0_clkdiv; // @ 0x20 + union { + uint32_t value; + struct { + uint32_t pwm_thre1 : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } pwm0_thre1; // @ 0x24 + union { + uint32_t value; + struct { + uint32_t pwm_thre2 : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } pwm0_thre2; // @ 0x28 + union { + uint32_t value; + struct { + uint32_t pwm_period : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } pwm0_period; // @ 0x2c + union { + uint32_t value; + struct { + uint32_t reg_clk_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pwm_out_inv : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pwm_stop_mode : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pwm_sw_force_val : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pwm_sw_mode : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pwm_stop_en : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t pwm_sts_top : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t pad0 : 24; + }; + } pwm0_config; // @ 0x30 + union { + uint32_t value; + struct { + uint32_t pwm_int_period_cnt : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pwm_int_enable : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad0 : 15; + }; + } pwm0_interrupt; // @ 0x34 + uint8_t pad1[0x8]; + union { + uint32_t value; + struct { + uint32_t pwm_clk_div : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } pwm1_clkdiv; // @ 0x40 + union { + uint32_t value; + struct { + uint32_t pwm_thre1 : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } pwm1_thre1; // @ 0x44 + union { + uint32_t value; + struct { + uint32_t pwm_thre2 : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } pwm1_thre2; // @ 0x48 + union { + uint32_t value; + struct { + uint32_t pwm_period : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } pwm1_period; // @ 0x4c + union { + uint32_t value; + struct { + uint32_t reg_clk_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pwm_out_inv : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pwm_stop_mode : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pwm_sw_force_val : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pwm_sw_mode : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pwm_stop_en : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t pwm_sts_top : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t pad0 : 24; + }; + } pwm1_config; // @ 0x50 + union { + uint32_t value; + struct { + uint32_t pwm_int_period_cnt : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pwm_int_enable : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad0 : 15; + }; + } pwm1_interrupt; // @ 0x54 + uint8_t pad2[0x8]; + union { + uint32_t value; + struct { + uint32_t pwm_clk_div : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } pwm2_clkdiv; // @ 0x60 + union { + uint32_t value; + struct { + uint32_t pwm_thre1 : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } pwm2_thre1; // @ 0x64 + union { + uint32_t value; + struct { + uint32_t pwm_thre2 : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } pwm2_thre2; // @ 0x68 + union { + uint32_t value; + struct { + uint32_t pwm_period : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } pwm2_period; // @ 0x6c + union { + uint32_t value; + struct { + uint32_t reg_clk_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pwm_out_inv : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pwm_stop_mode : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pwm_sw_force_val : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pwm_sw_mode : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pwm_stop_en : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t pwm_sts_top : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t pad0 : 24; + }; + } pwm2_config; // @ 0x70 + union { + uint32_t value; + struct { + uint32_t pwm_int_period_cnt : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pwm_int_enable : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad0 : 15; + }; + } pwm2_interrupt; // @ 0x74 + uint8_t pad3[0x8]; + union { + uint32_t value; + struct { + uint32_t pwm_clk_div : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } pwm3_clkdiv; // @ 0x80 + union { + uint32_t value; + struct { + uint32_t pwm_thre1 : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } pwm3_thre1; // @ 0x84 + union { + uint32_t value; + struct { + uint32_t pwm_thre2 : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } pwm3_thre2; // @ 0x88 + union { + uint32_t value; + struct { + uint32_t pwm_period : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } pwm3_period; // @ 0x8c + union { + uint32_t value; + struct { + uint32_t reg_clk_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pwm_out_inv : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pwm_stop_mode : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pwm_sw_force_val : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pwm_sw_mode : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pwm_stop_en : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t pwm_sts_top : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t pad0 : 24; + }; + } pwm3_config; // @ 0x90 + union { + uint32_t value; + struct { + uint32_t pwm_int_period_cnt : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pwm_int_enable : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad0 : 15; + }; + } pwm3_interrupt; // @ 0x94 + uint8_t pad4[0x8]; + union { + uint32_t value; + struct { + uint32_t pwm_clk_div : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } pwm4_clkdiv; // @ 0xa0 + union { + uint32_t value; + struct { + uint32_t pwm_thre1 : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } pwm4_thre1; // @ 0xa4 + union { + uint32_t value; + struct { + uint32_t pwm_thre2 : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } pwm4_thre2; // @ 0xa8 + union { + uint32_t value; + struct { + uint32_t pwm_period : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } pwm4_period; // @ 0xac + union { + uint32_t value; + struct { + uint32_t reg_clk_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pwm_out_inv : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pwm_stop_mode : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pwm_sw_force_val : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pwm_sw_mode : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pwm_stop_en : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t pwm_sts_top : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t pad0 : 24; + }; + } pwm4_config; // @ 0xb0 + union { + uint32_t value; + struct { + uint32_t pwm_int_period_cnt : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pwm_int_enable : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t pad0 : 15; + }; + } pwm4_interrupt; // @ 0xb4 + }; +} pwm_regs; +#define PWM_BASE 0x4000a400 +#define PWM ((pwm_regs* volatile)(PWM_BASE)) \ No newline at end of file diff --git a/src/include/soc/sec_dbg.h b/src/include/soc/sec_dbg.h new file mode 100644 index 0000000..8687274 --- /dev/null +++ b/src/include/soc/sec_dbg.h @@ -0,0 +1,62 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + union { + uint32_t value; + struct { + uint32_t sd_chip_id_low : 32; // @ 31 -- 0 # 0x0 + }; + } sd_chip_id_low; // @ 0x0 + union { + uint32_t value; + struct { + uint32_t sd_chip_id_high : 32; // @ 31 -- 0 # 0x0 + }; + } sd_chip_id_high; // @ 0x4 + union { + uint32_t value; + struct { + uint32_t sd_wifi_mac_low : 32; // @ 31 -- 0 # 0x0 + }; + } sd_wifi_mac_low; // @ 0x8 + union { + uint32_t value; + struct { + uint32_t sd_wifi_mac_high : 32; // @ 31 -- 0 # 0x0 + }; + } sd_wifi_mac_high; // @ 0xc + union { + uint32_t value; + struct { + uint32_t sd_dbg_pwd_low : 32; // @ 31 -- 0 # 0x0 + }; + } sd_dbg_pwd_low; // @ 0x10 + union { + uint32_t value; + struct { + uint32_t sd_dbg_pwd_high : 32; // @ 31 -- 0 # 0x0 + }; + } sd_dbg_pwd_high; // @ 0x14 + union { + uint32_t value; + struct { + uint32_t sd_dbg_pwd_busy : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t sd_dbg_pwd_trig : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t sd_dbg_cci_read_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t sd_dbg_cci_clk_sel : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t sd_dbg_pwd_cnt : 20; // @ 23 -- 4 # 0xff00000f + uint32_t sd_dbg_mode : 4; // @ 27 -- 24 # 0xf0ffffff + uint32_t sd_dbg_ena : 4; // @ 31 -- 28 # 0xfffffff + }; + } sd_status; // @ 0x18 + union { + uint32_t value; + struct { + uint32_t sd_dbg_reserved : 32; // @ 31 -- 0 # 0x0 + }; + } sd_dbg_reserved; // @ 0x1c + }; +} sec_dbg_regs; +#define SEC_DBG_BASE 0x40003000 +#define SEC_DBG ((sec_dbg_regs* volatile)(SEC_DBG_BASE)) \ No newline at end of file diff --git a/src/include/soc/sec_eng.h b/src/include/soc/sec_eng.h new file mode 100644 index 0000000..be41930 --- /dev/null +++ b/src/include/soc/sec_eng.h @@ -0,0 +1,624 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + union { + uint32_t value; + struct { + uint32_t se_sha_0_busy : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t se_sha_0_trig_1t : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t se_sha_0_mode : 3; // @ 4 -- 2 # 0xffffffe3 + uint32_t se_sha_0_en : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t se_sha_0_hash_sel : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t pad0 : 1; + uint32_t se_sha_0_int : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t se_sha_0_int_clr_1t : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t se_sha_0_int_set_1t : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t se_sha_0_int_mask : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t pad1 : 3; + uint32_t se_sha_0_link_mode : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t se_sha_0_msg_len : 16; // @ 31 -- 16 # 0xffff + }; + } se_sha_0_ctrl; // @ 0x0 + union { + uint32_t value; + struct { + uint32_t se_sha_0_msa : 32; // @ 31 -- 0 # 0x0 + }; + } se_sha_0_msa; // @ 0x4 + union { + uint32_t value; + struct { + uint32_t se_sha_0_status : 32; // @ 31 -- 0 # 0x0 + }; + } se_sha_0_status; // @ 0x8 + union { + uint32_t value; + struct { + uint32_t se_sha_0_dout_endian : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 31; + }; + } se_sha_0_endian; // @ 0xc + union { + uint32_t value; + struct { + uint32_t se_sha_0_hash_l_0 : 32; // @ 31 -- 0 # 0x0 + }; + } se_sha_0_hash_l_0; // @ 0x10 + union { + uint32_t value; + struct { + uint32_t se_sha_0_hash_l_1 : 32; // @ 31 -- 0 # 0x0 + }; + } se_sha_0_hash_l_1; // @ 0x14 + union { + uint32_t value; + struct { + uint32_t se_sha_0_hash_l_2 : 32; // @ 31 -- 0 # 0x0 + }; + } se_sha_0_hash_l_2; // @ 0x18 + union { + uint32_t value; + struct { + uint32_t se_sha_0_hash_l_3 : 32; // @ 31 -- 0 # 0x0 + }; + } se_sha_0_hash_l_3; // @ 0x1c + union { + uint32_t value; + struct { + uint32_t se_sha_0_hash_l_4 : 32; // @ 31 -- 0 # 0x0 + }; + } se_sha_0_hash_l_4; // @ 0x20 + union { + uint32_t value; + struct { + uint32_t se_sha_0_hash_l_5 : 32; // @ 31 -- 0 # 0x0 + }; + } se_sha_0_hash_l_5; // @ 0x24 + union { + uint32_t value; + struct { + uint32_t se_sha_0_hash_l_6 : 32; // @ 31 -- 0 # 0x0 + }; + } se_sha_0_hash_l_6; // @ 0x28 + union { + uint32_t value; + struct { + uint32_t se_sha_0_hash_l_7 : 32; // @ 31 -- 0 # 0x0 + }; + } se_sha_0_hash_l_7; // @ 0x2c + union { + uint32_t value; + struct { + uint32_t se_sha_0_hash_h_0 : 32; // @ 31 -- 0 # 0x0 + }; + } se_sha_0_hash_h_0; // @ 0x30 + union { + uint32_t value; + struct { + uint32_t se_sha_0_hash_h_1 : 32; // @ 31 -- 0 # 0x0 + }; + } se_sha_0_hash_h_1; // @ 0x34 + union { + uint32_t value; + struct { + uint32_t se_sha_0_hash_h_2 : 32; // @ 31 -- 0 # 0x0 + }; + } se_sha_0_hash_h_2; // @ 0x38 + union { + uint32_t value; + struct { + uint32_t se_sha_0_hash_h_3 : 32; // @ 31 -- 0 # 0x0 + }; + } se_sha_0_hash_h_3; // @ 0x3c + union { + uint32_t value; + struct { + uint32_t se_sha_0_hash_h_4 : 32; // @ 31 -- 0 # 0x0 + }; + } se_sha_0_hash_h_4; // @ 0x40 + union { + uint32_t value; + struct { + uint32_t se_sha_0_hash_h_5 : 32; // @ 31 -- 0 # 0x0 + }; + } se_sha_0_hash_h_5; // @ 0x44 + union { + uint32_t value; + struct { + uint32_t se_sha_0_hash_h_6 : 32; // @ 31 -- 0 # 0x0 + }; + } se_sha_0_hash_h_6; // @ 0x48 + union { + uint32_t value; + struct { + uint32_t se_sha_0_hash_h_7 : 32; // @ 31 -- 0 # 0x0 + }; + } se_sha_0_hash_h_7; // @ 0x4c + union { + uint32_t value; + struct { + uint32_t se_sha_0_lca : 32; // @ 31 -- 0 # 0x0 + }; + } se_sha_0_link; // @ 0x50 + uint8_t pad0[0xa8]; + union { + uint32_t value; + struct { + uint32_t se_sha_prot_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t se_sha_id0_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t se_sha_id1_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 29; + }; + } se_sha_0_ctrl_prot; // @ 0xfc + union { + uint32_t value; + struct { + uint32_t se_aes_0_busy : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t se_aes_0_trig_1t : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t se_aes_0_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t se_aes_0_mode : 2; // @ 4 -- 3 # 0xffffffe7 + uint32_t se_aes_0_dec_en : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t se_aes_0_dec_key_sel : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t se_aes_0_hw_key_en : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t se_aes_0_int : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t se_aes_0_int_clr_1t : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t se_aes_0_int_set_1t : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t se_aes_0_int_mask : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t se_aes_0_block_mode : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t se_aes_0_iv_sel : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t se_aes_0_link_mode : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t se_aes_0_msg_len : 16; // @ 31 -- 16 # 0xffff + }; + } se_aes_0_ctrl; // @ 0x100 + union { + uint32_t value; + struct { + uint32_t se_aes_0_msa : 32; // @ 31 -- 0 # 0x0 + }; + } se_aes_0_msa; // @ 0x104 + union { + uint32_t value; + struct { + uint32_t se_aes_0_mda : 32; // @ 31 -- 0 # 0x0 + }; + } se_aes_0_mda; // @ 0x108 + union { + uint32_t value; + struct { + uint32_t se_aes_0_status : 32; // @ 31 -- 0 # 0x0 + }; + } se_aes_0_status; // @ 0x10c + union { + uint32_t value; + struct { + uint32_t se_aes_0_iv_0 : 32; // @ 31 -- 0 # 0x0 + }; + } se_aes_0_iv_0; // @ 0x110 + union { + uint32_t value; + struct { + uint32_t se_aes_0_iv_1 : 32; // @ 31 -- 0 # 0x0 + }; + } se_aes_0_iv_1; // @ 0x114 + union { + uint32_t value; + struct { + uint32_t se_aes_0_iv_2 : 32; // @ 31 -- 0 # 0x0 + }; + } se_aes_0_iv_2; // @ 0x118 + union { + uint32_t value; + struct { + uint32_t se_aes_0_iv_3 : 32; // @ 31 -- 0 # 0x0 + }; + } se_aes_0_iv_3; // @ 0x11c + union { + uint32_t value; + struct { + uint32_t se_aes_0_key_0 : 32; // @ 31 -- 0 # 0x0 + }; + } se_aes_0_key_0; // @ 0x120 + union { + uint32_t value; + struct { + uint32_t se_aes_0_key_1 : 32; // @ 31 -- 0 # 0x0 + }; + } se_aes_0_key_1; // @ 0x124 + union { + uint32_t value; + struct { + uint32_t se_aes_0_key_2 : 32; // @ 31 -- 0 # 0x0 + }; + } se_aes_0_key_2; // @ 0x128 + union { + uint32_t value; + struct { + uint32_t se_aes_0_key_3 : 32; // @ 31 -- 0 # 0x0 + }; + } se_aes_0_key_3; // @ 0x12c + union { + uint32_t value; + struct { + uint32_t se_aes_0_key_4 : 32; // @ 31 -- 0 # 0x0 + }; + } se_aes_0_key_4; // @ 0x130 + union { + uint32_t value; + struct { + uint32_t se_aes_0_key_5 : 32; // @ 31 -- 0 # 0x0 + }; + } se_aes_0_key_5; // @ 0x134 + union { + uint32_t value; + struct { + uint32_t se_aes_0_key_6 : 32; // @ 31 -- 0 # 0x0 + }; + } se_aes_0_key_6; // @ 0x138 + union { + uint32_t value; + struct { + uint32_t se_aes_0_key_7 : 32; // @ 31 -- 0 # 0x0 + }; + } se_aes_0_key_7; // @ 0x13c + union { + uint32_t value; + struct { + uint32_t se_aes_0_key_sel_0 : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 30; + }; + } se_aes_0_key_sel_0; // @ 0x140 + union { + uint32_t value; + struct { + uint32_t se_aes_0_key_sel_1 : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 30; + }; + } se_aes_0_key_sel_1; // @ 0x144 + union { + uint32_t value; + struct { + uint32_t se_aes_0_dout_endian : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t se_aes_0_din_endian : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t se_aes_0_key_endian : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t se_aes_0_iv_endian : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pad0 : 26; + uint32_t se_aes_0_ctr_len : 2; // @ 31 -- 30 # 0x3fffffff + }; + } se_aes_0_endian; // @ 0x148 + union { + uint32_t value; + struct { + uint32_t se_aes_0_sboot_key_sel : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 31; + }; + } se_aes_0_sboot; // @ 0x14c + union { + uint32_t value; + struct { + uint32_t se_aes_0_lca : 32; // @ 31 -- 0 # 0x0 + }; + } se_aes_0_link; // @ 0x150 + uint8_t pad1[0xa8]; + union { + uint32_t value; + struct { + uint32_t se_aes_prot_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t se_aes_id0_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t se_aes_id1_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 29; + }; + } se_aes_0_ctrl_prot; // @ 0x1fc + union { + uint32_t value; + struct { + uint32_t se_trng_0_busy : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t se_trng_0_trig_1t : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t se_trng_0_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t se_trng_0_dout_clr_1t : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t se_trng_0_ht_error : 1; // @ 4 -- 4 # 0xffffffef + uint32_t pad0 : 3; + uint32_t se_trng_0_int : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t se_trng_0_int_clr_1t : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t se_trng_0_int_set_1t : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t se_trng_0_int_mask : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t pad1 : 1; + uint32_t se_trng_0_manual_fun_sel : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t se_trng_0_manual_reseed : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t se_trng_0_manual_en : 1; // @ 15 -- 15 # 0xffff7fff + uint32_t pad2 : 16; + }; + } se_trng_0_ctrl_0; // @ 0x200 + union { + uint32_t value; + struct { + uint32_t se_trng_0_status : 32; // @ 31 -- 0 # 0x0 + }; + } se_trng_0_status; // @ 0x204 + union { + uint32_t value; + struct { + uint32_t se_trng_0_dout_0 : 32; // @ 31 -- 0 # 0x0 + }; + } se_trng_0_dout_0; // @ 0x208 + union { + uint32_t value; + struct { + uint32_t se_trng_0_dout_1 : 32; // @ 31 -- 0 # 0x0 + }; + } se_trng_0_dout_1; // @ 0x20c + union { + uint32_t value; + struct { + uint32_t se_trng_0_dout_2 : 32; // @ 31 -- 0 # 0x0 + }; + } se_trng_0_dout_2; // @ 0x210 + union { + uint32_t value; + struct { + uint32_t se_trng_0_dout_3 : 32; // @ 31 -- 0 # 0x0 + }; + } se_trng_0_dout_3; // @ 0x214 + union { + uint32_t value; + struct { + uint32_t se_trng_0_dout_4 : 32; // @ 31 -- 0 # 0x0 + }; + } se_trng_0_dout_4; // @ 0x218 + union { + uint32_t value; + struct { + uint32_t se_trng_0_dout_5 : 32; // @ 31 -- 0 # 0x0 + }; + } se_trng_0_dout_5; // @ 0x21c + union { + uint32_t value; + struct { + uint32_t se_trng_0_dout_6 : 32; // @ 31 -- 0 # 0x0 + }; + } se_trng_0_dout_6; // @ 0x220 + union { + uint32_t value; + struct { + uint32_t se_trng_0_dout_7 : 32; // @ 31 -- 0 # 0x0 + }; + } se_trng_0_dout_7; // @ 0x224 + union { + uint32_t value; + struct { + uint32_t se_trng_0_test_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t se_trng_0_cp_test_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t se_trng_0_cp_bypass : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t se_trng_0_ht_dis : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t se_trng_0_ht_alarm_n : 8; // @ 11 -- 4 # 0xfffff00f + uint32_t pad0 : 20; + }; + } se_trng_0_test; // @ 0x228 + union { + uint32_t value; + struct { + uint32_t se_trng_0_reseed_n_lsb : 32; // @ 31 -- 0 # 0x0 + }; + } se_trng_0_ctrl_1; // @ 0x22c + union { + uint32_t value; + struct { + uint32_t se_trng_0_reseed_n_msb : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } se_trng_0_ctrl_2; // @ 0x230 + union { + uint32_t value; + struct { + uint32_t se_trng_0_cp_ratio : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t se_trng_0_ht_rct_c : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t se_trng_0_ht_apt_c : 10; // @ 25 -- 16 # 0xfc00ffff + uint32_t se_trng_0_ht_od_en : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t pad0 : 4; + uint32_t se_trng_0_rosc_en : 1; // @ 31 -- 31 # 0x7fffffff + }; + } se_trng_0_ctrl_3; // @ 0x234 + uint8_t pad2[0x8]; + union { + uint32_t value; + struct { + uint32_t se_trng_0_test_out_0 : 32; // @ 31 -- 0 # 0x0 + }; + } se_trng_0_test_out_0; // @ 0x240 + union { + uint32_t value; + struct { + uint32_t se_trng_0_test_out_1 : 32; // @ 31 -- 0 # 0x0 + }; + } se_trng_0_test_out_1; // @ 0x244 + union { + uint32_t value; + struct { + uint32_t se_trng_0_test_out_2 : 32; // @ 31 -- 0 # 0x0 + }; + } se_trng_0_test_out_2; // @ 0x248 + union { + uint32_t value; + struct { + uint32_t se_trng_0_test_out_3 : 32; // @ 31 -- 0 # 0x0 + }; + } se_trng_0_test_out_3; // @ 0x24c + uint8_t pad3[0xac]; + union { + uint32_t value; + struct { + uint32_t se_trng_prot_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t se_trng_id0_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t se_trng_id1_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 29; + }; + } se_trng_0_ctrl_prot; // @ 0x2fc + union { + uint32_t value; + struct { + uint32_t se_pka_0_done : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t se_pka_0_done_clr_1t : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t se_pka_0_busy : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t se_pka_0_en : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t se_pka_0_prot_md : 4; // @ 7 -- 4 # 0xffffff0f + uint32_t se_pka_0_int : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t se_pka_0_int_clr_1t : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t se_pka_0_int_set : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t se_pka_0_int_mask : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t se_pka_0_endian : 1; // @ 12 -- 12 # 0xffffefff + uint32_t se_pka_0_ram_clr_md : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t pad0 : 2; + uint32_t se_pka_0_status_clr_1t : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t se_pka_0_status : 15; // @ 31 -- 17 # 0x1ffff + }; + } se_pka_0_ctrl_0; // @ 0x300 + uint8_t pad4[0x8]; + union { + uint32_t value; + struct { + uint32_t se_pka_0_seed : 32; // @ 31 -- 0 # 0x0 + }; + } se_pka_0_seed; // @ 0x30c + union { + uint32_t value; + struct { + uint32_t se_pka_0_hburst : 3; // @ 2 -- 0 # 0xfffffff8 + uint32_t se_pka_0_hbypass : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pad0 : 28; + }; + } se_pka_0_ctrl_1; // @ 0x310 + uint8_t pad5[0x2c]; + uint32_t se_pka_0_rw; // @ 0x340 + uint8_t pad6[0x1c]; + uint32_t se_pka_0_rw_burst; // @ 0x360 + uint8_t pad7[0x98]; + union { + uint32_t value; + struct { + uint32_t se_pka_prot_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t se_pka_id0_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t se_pka_id1_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 29; + }; + } se_pka_0_ctrl_prot; // @ 0x3fc + union { + uint32_t value; + struct { + uint32_t se_cdet_0_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t se_cdet_0_error : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t se_cdet_0_status : 14; // @ 15 -- 2 # 0xffff0003 + uint32_t se_cdet_0_g_loop_max : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t se_cdet_0_g_loop_min : 8; // @ 31 -- 24 # 0xffffff + }; + } se_cdet_0_ctrl_0; // @ 0x400 + union { + uint32_t value; + struct { + uint32_t se_cdet_0_t_loop_n : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t se_cdet_0_t_dly_n : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t se_cdet_0_g_slp_n : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t pad0 : 8; + }; + } se_cdet_0_ctrl_1; // @ 0x404 + uint8_t pad8[0xf4]; + union { + uint32_t value; + struct { + uint32_t se_cdet_prot_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t se_cdet_id0_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t se_cdet_id1_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 29; + }; + } se_cdet_0_ctrl_prot; // @ 0x4fc + union { + uint32_t value; + struct { + uint32_t se_gmac_0_busy : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t se_gmac_0_trig_1t : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t se_gmac_0_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 5; + uint32_t se_gmac_0_int : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t se_gmac_0_int_clr_1t : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t se_gmac_0_int_set_1t : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t se_gmac_0_int_mask : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t se_gmac_0_t_endian : 1; // @ 12 -- 12 # 0xffffefff + uint32_t se_gmac_0_h_endian : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t se_gmac_0_x_endian : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t pad1 : 17; + }; + } se_gmac_0_ctrl_0; // @ 0x500 + union { + uint32_t value; + struct { + uint32_t se_gmac_0_lca : 32; // @ 31 -- 0 # 0x0 + }; + } se_gmac_0_lca; // @ 0x504 + union { + uint32_t value; + struct { + uint32_t se_gmac_0_status : 32; // @ 31 -- 0 # 0x0 + }; + } se_gmac_0_status; // @ 0x508 + uint8_t pad9[0xf0]; + union { + uint32_t value; + struct { + uint32_t se_gmac_prot_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t se_gmac_id0_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t se_gmac_id1_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 29; + }; + } se_gmac_0_ctrl_prot; // @ 0x5fc + uint8_t pad10[0x900]; + union { + uint32_t value; + struct { + uint32_t se_sha_prot_en_rd : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t se_sha_id0_en_rd : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t se_sha_id1_en_rd : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 1; + uint32_t se_aes_prot_en_rd : 1; // @ 4 -- 4 # 0xffffffef + uint32_t se_aes_id0_en_rd : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t se_aes_id1_en_rd : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t pad1 : 1; + uint32_t se_trng_prot_en_rd : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t se_trng_id0_en_rd : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t se_trng_id1_en_rd : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t pad2 : 1; + uint32_t se_pka_prot_en_rd : 1; // @ 12 -- 12 # 0xffffefff + uint32_t se_pka_id0_en_rd : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t se_pka_id1_en_rd : 1; // @ 14 -- 14 # 0xffffbfff + uint32_t pad3 : 1; + uint32_t se_cdet_prot_en_rd : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t se_cdet_id0_en_rd : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t se_cdet_id1_en_rd : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t pad4 : 1; + uint32_t se_gmac_prot_en_rd : 1; // @ 20 -- 20 # 0xffefffff + uint32_t se_gmac_id0_en_rd : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t se_gmac_id1_en_rd : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t pad5 : 8; + uint32_t se_dbg_dis : 1; // @ 31 -- 31 # 0x7fffffff + }; + } se_ctrl_prot_rd; // @ 0xf00 + union { + uint32_t value; + struct { + uint32_t se_ctrl_reserved_0 : 32; // @ 31 -- 0 # 0x0 + }; + } se_ctrl_reserved_0; // @ 0xf04 + union { + uint32_t value; + struct { + uint32_t se_ctrl_reserved_1 : 32; // @ 31 -- 0 # 0x0 + }; + } se_ctrl_reserved_1; // @ 0xf08 + union { + uint32_t value; + struct { + uint32_t se_ctrl_reserved_2 : 32; // @ 31 -- 0 # 0x0 + }; + } se_ctrl_reserved_2; // @ 0xf0c + }; +} sec_eng_regs; +#define SEC_ENG_BASE 0x40004000 +#define SEC_ENG ((sec_eng_regs* volatile)(SEC_ENG_BASE)) \ No newline at end of file diff --git a/src/include/soc/sf_ctrl.h b/src/include/soc/sf_ctrl.h new file mode 100644 index 0000000..5eaec5c --- /dev/null +++ b/src/include/soc/sf_ctrl.h @@ -0,0 +1,667 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + union { + uint32_t value; + struct { + uint32_t pad0 : 2; + uint32_t sf_clk_sf_rx_inv_sel : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t sf_clk_out_gate_en : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t sf_clk_out_inv_sel : 1; // @ 4 -- 4 # 0xffffffef + uint32_t sf_clk_sahb_sram_sel : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad1 : 2; + uint32_t sf_if_read_dly_n : 3; // @ 10 -- 8 # 0xfffff8ff + uint32_t sf_if_read_dly_en : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t pad2 : 4; + uint32_t sf_if_int : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t sf_if_int_clr : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t sf_if_int_set : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t sf_aes_dly_mode : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t sf_aes_dout_endian : 1; // @ 20 -- 20 # 0xffefffff + uint32_t sf_aes_ctr_plus_en : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t sf_aes_key_endian : 1; // @ 22 -- 22 # 0xffbfffff + uint32_t sf_aes_iv_endian : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t sf_id : 8; // @ 31 -- 24 # 0xffffff + }; + } sf_ctrl_0; // @ 0x0 + union { + uint32_t value; + struct { + uint32_t sf_if_sr_pat_mask : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t sf_if_sr_pat : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t sf_if_sr_int : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t sf_if_sr_int_en : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t sf_if_sr_int_set : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t pad0 : 1; + uint32_t sf_if_0_ack_lat : 3; // @ 22 -- 20 # 0xff8fffff + uint32_t pad1 : 1; + uint32_t sf_if_reg_hold : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t sf_if_reg_wp : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t sf_ahb2sif_stopped : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t sf_ahb2sif_stop : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t sf_if_fn_sel : 1; // @ 28 -- 28 # 0xefffffff + uint32_t sf_if_en : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t sf_ahb2sif_en : 1; // @ 30 -- 30 # 0xbfffffff + uint32_t sf_ahb2sram_en : 1; // @ 31 -- 31 # 0x7fffffff + }; + } sf_ctrl_1; // @ 0x4 + union { + uint32_t value; + struct { + uint32_t sf_if_busy : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t sf_if_0_trig : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t sf_if_0_dat_byte : 10; // @ 11 -- 2 # 0xfffff003 + uint32_t sf_if_0_dmy_byte : 5; // @ 16 -- 12 # 0xfffe0fff + uint32_t sf_if_0_adr_byte : 3; // @ 19 -- 17 # 0xfff1ffff + uint32_t sf_if_0_cmd_byte : 3; // @ 22 -- 20 # 0xff8fffff + uint32_t sf_if_0_dat_rw : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t sf_if_0_dat_en : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t sf_if_0_dmy_en : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t sf_if_0_adr_en : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t sf_if_0_cmd_en : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t sf_if_0_spi_mode : 3; // @ 30 -- 28 # 0x8fffffff + uint32_t sf_if_0_qpi_mode_en : 1; // @ 31 -- 31 # 0x7fffffff + }; + } sf_if_sahb_0; // @ 0x8 + union { + uint32_t value; + struct { + uint32_t sf_if_0_cmd_buf_0 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_if_sahb_1; // @ 0xc + union { + uint32_t value; + struct { + uint32_t sf_if_0_cmd_buf_1 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_if_sahb_2; // @ 0x10 + union { + uint32_t value; + struct { + uint32_t pad0 : 12; + uint32_t sf_if_1_dmy_byte : 5; // @ 16 -- 12 # 0xfffe0fff + uint32_t sf_if_1_adr_byte : 3; // @ 19 -- 17 # 0xfff1ffff + uint32_t sf_if_1_cmd_byte : 3; // @ 22 -- 20 # 0xff8fffff + uint32_t sf_if_1_dat_rw : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t sf_if_1_dat_en : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t sf_if_1_dmy_en : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t sf_if_1_adr_en : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t sf_if_1_cmd_en : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t sf_if_1_spi_mode : 3; // @ 30 -- 28 # 0x8fffffff + uint32_t sf_if_1_qpi_mode_en : 1; // @ 31 -- 31 # 0x7fffffff + }; + } sf_if_iahb_0; // @ 0x14 + union { + uint32_t value; + struct { + uint32_t sf_if_1_cmd_buf_0 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_if_iahb_1; // @ 0x18 + union { + uint32_t value; + struct { + uint32_t sf_if_1_cmd_buf_1 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_if_iahb_2; // @ 0x1c + union { + uint32_t value; + struct { + uint32_t sf_if_status_0 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_if_status_0; // @ 0x20 + union { + uint32_t value; + struct { + uint32_t sf_if_status_1 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_if_status_1; // @ 0x24 + union { + uint32_t value; + struct { + uint32_t sf_aes_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t sf_aes_mode : 2; // @ 2 -- 1 # 0xfffffff9 + uint32_t sf_aes_pref_trig : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t sf_aes_pref_busy : 1; // @ 4 -- 4 # 0xffffffef + uint32_t sf_aes_status : 27; // @ 31 -- 5 # 0x1f + }; + } sf_aes; // @ 0x28 + union { + uint32_t value; + struct { + uint32_t sf_ahb2sif_status : 32; // @ 31 -- 0 # 0x0 + }; + } sf_ahb2sif_status; // @ 0x2c + union { + uint32_t value; + struct { + uint32_t sf_cs_dly_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 6; + uint32_t sf_clk_out_dly_sel : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad1 : 16; + uint32_t sf_dqs_oe_dly_sel : 2; // @ 27 -- 26 # 0xf3ffffff + uint32_t sf_dqs_di_dly_sel : 2; // @ 29 -- 28 # 0xcfffffff + uint32_t sf_dqs_do_dly_sel : 2; // @ 31 -- 30 # 0x3fffffff + }; + } sf_if_io_dly_0; // @ 0x30 + union { + uint32_t value; + struct { + uint32_t sf_io_0_oe_dly_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 6; + uint32_t sf_io_0_di_dly_sel : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad1 : 6; + uint32_t sf_io_0_do_dly_sel : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad2 : 14; + }; + } sf_if_io_dly_1; // @ 0x34 + union { + uint32_t value; + struct { + uint32_t sf_io_1_oe_dly_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 6; + uint32_t sf_io_1_di_dly_sel : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad1 : 6; + uint32_t sf_io_1_do_dly_sel : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad2 : 14; + }; + } sf_if_io_dly_2; // @ 0x38 + union { + uint32_t value; + struct { + uint32_t sf_io_2_oe_dly_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 6; + uint32_t sf_io_2_di_dly_sel : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad1 : 6; + uint32_t sf_io_2_do_dly_sel : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad2 : 14; + }; + } sf_if_io_dly_3; // @ 0x3c + union { + uint32_t value; + struct { + uint32_t sf_io_3_oe_dly_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 6; + uint32_t sf_io_3_di_dly_sel : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad1 : 6; + uint32_t sf_io_3_do_dly_sel : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad2 : 14; + }; + } sf_if_io_dly_4; // @ 0x40 + union { + uint32_t value; + struct { + uint32_t sf_reserved : 32; // @ 31 -- 0 # 0x0 + }; + } sf_reserved; // @ 0x44 + union { + uint32_t value; + struct { + uint32_t sf2_cs_dly_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 6; + uint32_t sf2_clk_out_dly_sel : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad1 : 16; + uint32_t sf2_dqs_oe_dly_sel : 2; // @ 27 -- 26 # 0xf3ffffff + uint32_t sf2_dqs_di_dly_sel : 2; // @ 29 -- 28 # 0xcfffffff + uint32_t sf2_dqs_do_dly_sel : 2; // @ 31 -- 30 # 0x3fffffff + }; + } sf2_if_io_dly_0; // @ 0x48 + union { + uint32_t value; + struct { + uint32_t sf2_io_0_oe_dly_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 6; + uint32_t sf2_io_0_di_dly_sel : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad1 : 6; + uint32_t sf2_io_0_do_dly_sel : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad2 : 14; + }; + } sf2_if_io_dly_1; // @ 0x4c + union { + uint32_t value; + struct { + uint32_t sf2_io_1_oe_dly_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 6; + uint32_t sf2_io_1_di_dly_sel : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad1 : 6; + uint32_t sf2_io_1_do_dly_sel : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad2 : 14; + }; + } sf2_if_io_dly_2; // @ 0x50 + union { + uint32_t value; + struct { + uint32_t sf2_io_2_oe_dly_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 6; + uint32_t sf2_io_2_di_dly_sel : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad1 : 6; + uint32_t sf2_io_2_do_dly_sel : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad2 : 14; + }; + } sf2_if_io_dly_3; // @ 0x54 + union { + uint32_t value; + struct { + uint32_t sf2_io_3_oe_dly_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 6; + uint32_t sf2_io_3_di_dly_sel : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad1 : 6; + uint32_t sf2_io_3_do_dly_sel : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad2 : 14; + }; + } sf2_if_io_dly_4; // @ 0x58 + union { + uint32_t value; + struct { + uint32_t sf3_cs_dly_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 6; + uint32_t sf3_clk_out_dly_sel : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad1 : 16; + uint32_t sf3_dqs_oe_dly_sel : 2; // @ 27 -- 26 # 0xf3ffffff + uint32_t sf3_dqs_di_dly_sel : 2; // @ 29 -- 28 # 0xcfffffff + uint32_t sf3_dqs_do_dly_sel : 2; // @ 31 -- 30 # 0x3fffffff + }; + } sf3_if_io_dly_0; // @ 0x5c + union { + uint32_t value; + struct { + uint32_t sf3_io_0_oe_dly_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 6; + uint32_t sf3_io_0_di_dly_sel : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad1 : 6; + uint32_t sf3_io_0_do_dly_sel : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad2 : 14; + }; + } sf3_if_io_dly_1; // @ 0x60 + union { + uint32_t value; + struct { + uint32_t sf3_io_1_oe_dly_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 6; + uint32_t sf3_io_1_di_dly_sel : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad1 : 6; + uint32_t sf3_io_1_do_dly_sel : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad2 : 14; + }; + } sf3_if_io_dly_2; // @ 0x64 + union { + uint32_t value; + struct { + uint32_t sf3_io_2_oe_dly_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 6; + uint32_t sf3_io_2_di_dly_sel : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad1 : 6; + uint32_t sf3_io_2_do_dly_sel : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad2 : 14; + }; + } sf3_if_io_dly_3; // @ 0x68 + union { + uint32_t value; + struct { + uint32_t sf3_io_3_oe_dly_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 6; + uint32_t sf3_io_3_di_dly_sel : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad1 : 6; + uint32_t sf3_io_3_do_dly_sel : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad2 : 14; + }; + } sf3_if_io_dly_4; // @ 0x6c + union { + uint32_t value; + struct { + uint32_t sf_if_pad_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 1; + uint32_t sf_if_pad_sel_lock : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t sf_if_dtr_en : 1; // @ 4 -- 4 # 0xffffffef + uint32_t sf_if_dqs_en : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad1 : 26; + }; + } sf_ctrl_2; // @ 0x70 + union { + uint32_t value; + struct { + uint32_t sf_cmds_wrap_len : 4; // @ 3 -- 0 # 0xfffffff0 + uint32_t sf_cmds_en : 1; // @ 4 -- 4 # 0xffffffef + uint32_t sf_cmds_bt_dly : 3; // @ 7 -- 5 # 0xffffff1f + uint32_t sf_cmds_bt_en : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t sf_cmds_wrap_q_ini : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t sf_cmds_wrap_mode : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t pad0 : 18; + uint32_t sf_if_1_ack_lat : 3; // @ 31 -- 29 # 0x1fffffff + }; + } sf_ctrl_3; // @ 0x74 + union { + uint32_t value; + struct { + uint32_t pad0 : 12; + uint32_t sf_if_2_dmy_byte : 5; // @ 16 -- 12 # 0xfffe0fff + uint32_t sf_if_2_adr_byte : 3; // @ 19 -- 17 # 0xfff1ffff + uint32_t sf_if_2_cmd_byte : 3; // @ 22 -- 20 # 0xff8fffff + uint32_t sf_if_2_dat_rw : 1; // @ 23 -- 23 # 0xff7fffff + uint32_t sf_if_2_dat_en : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t sf_if_2_dmy_en : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t sf_if_2_adr_en : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t sf_if_2_cmd_en : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t sf_if_2_spi_mode : 3; // @ 30 -- 28 # 0x8fffffff + uint32_t sf_if_2_qpi_mode_en : 1; // @ 31 -- 31 # 0x7fffffff + }; + } sf_if_iahb_3; // @ 0x78 + union { + uint32_t value; + struct { + uint32_t sf_if_2_cmd_buf_0 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_if_iahb_4; // @ 0x7c + union { + uint32_t value; + struct { + uint32_t sf_if_2_cmd_buf_1 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_if_iahb_5; // @ 0x80 + union { + uint32_t value; + struct { + uint32_t pad0 : 20; + uint32_t sf_if_3_cmd_byte : 3; // @ 22 -- 20 # 0xff8fffff + uint32_t pad1 : 5; + uint32_t sf_if_3_spi_mode : 3; // @ 30 -- 28 # 0x8fffffff + uint32_t sf_if_3_qpi_mode_en : 1; // @ 31 -- 31 # 0x7fffffff + }; + } sf_if_iahb_6; // @ 0x84 + union { + uint32_t value; + struct { + uint32_t sf_if_3_cmd_buf_0 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_if_iahb_7; // @ 0x88 + uint8_t pad0[0x74]; + union { + uint32_t value; + struct { + uint32_t sf_ctrl_prot_en_rd : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t sf_ctrl_id0_en_rd : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t sf_ctrl_id1_en_rd : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 27; + uint32_t sf_if_0_trig_wr_lock : 1; // @ 30 -- 30 # 0xbfffffff + uint32_t sf_dbg_dis : 1; // @ 31 -- 31 # 0x7fffffff + }; + } sf_ctrl_prot_en_rd; // @ 0x100 + union { + uint32_t value; + struct { + uint32_t sf_ctrl_prot_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t sf_ctrl_id0_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t sf_ctrl_id1_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 29; + }; + } sf_ctrl_prot_en; // @ 0x104 + uint8_t pad1[0xf8]; + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r0_0 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r0_0; // @ 0x200 + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r0_1 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r0_1; // @ 0x204 + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r0_2 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r0_2; // @ 0x208 + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r0_3 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r0_3; // @ 0x20c + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r0_4 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r0_4; // @ 0x210 + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r0_5 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r0_5; // @ 0x214 + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r0_6 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r0_6; // @ 0x218 + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r0_7 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r0_7; // @ 0x21c + union { + uint32_t value; + struct { + uint32_t sf_aes_iv_r0_w0 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_iv_r0_w0; // @ 0x220 + union { + uint32_t value; + struct { + uint32_t sf_aes_iv_r0_w1 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_iv_r0_w1; // @ 0x224 + union { + uint32_t value; + struct { + uint32_t sf_aes_iv_r0_w2 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_iv_r0_w2; // @ 0x228 + union { + uint32_t value; + struct { + uint32_t sf_aes_iv_r0_w3 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_iv_r0_w3; // @ 0x22c + union { + uint32_t value; + struct { + uint32_t sf_aes_region_r0_end : 14; // @ 13 -- 0 # 0xffffc000 + uint32_t sf_aes_region_r0_start : 14; // @ 27 -- 14 # 0xf0003fff + uint32_t pad0 : 1; + uint32_t sf_aes_region_r0_hw_key_en : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t sf_aes_region_r0_en : 1; // @ 30 -- 30 # 0xbfffffff + uint32_t sf_aes_region_r0_lock : 1; // @ 31 -- 31 # 0x7fffffff + }; + } sf_aes_cfg_r0; // @ 0x230 + uint8_t pad2[0xcc]; + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r1_0 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r1_0; // @ 0x300 + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r1_1 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r1_1; // @ 0x304 + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r1_2 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r1_2; // @ 0x308 + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r1_3 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r1_3; // @ 0x30c + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r1_4 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r1_4; // @ 0x310 + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r1_5 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r1_5; // @ 0x314 + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r1_6 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r1_6; // @ 0x318 + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r1_7 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r1_7; // @ 0x31c + union { + uint32_t value; + struct { + uint32_t sf_aes_iv_r1_w0 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_iv_r1_w0; // @ 0x320 + union { + uint32_t value; + struct { + uint32_t sf_aes_iv_r1_w1 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_iv_r1_w1; // @ 0x324 + union { + uint32_t value; + struct { + uint32_t sf_aes_iv_r1_w2 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_iv_r1_w2; // @ 0x328 + union { + uint32_t value; + struct { + uint32_t sf_aes_iv_r1_w3 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_iv_r1_w3; // @ 0x32c + union { + uint32_t value; + struct { + uint32_t sf_aes_r1_end : 14; // @ 13 -- 0 # 0xffffc000 + uint32_t sf_aes_r1_start : 14; // @ 27 -- 14 # 0xf0003fff + uint32_t pad0 : 1; + uint32_t sf_aes_r1_hw_key_en : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t sf_aes_r1_en : 1; // @ 30 -- 30 # 0xbfffffff + uint32_t sf_aes_r1_lock : 1; // @ 31 -- 31 # 0x7fffffff + }; + } sf_aes_r1; // @ 0x330 + uint8_t pad3[0xcc]; + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r2_0 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r2_0; // @ 0x400 + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r2_1 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r2_1; // @ 0x404 + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r2_2 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r2_2; // @ 0x408 + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r2_3 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r2_3; // @ 0x40c + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r2_4 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r2_4; // @ 0x410 + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r2_5 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r2_5; // @ 0x414 + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r2_6 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r2_6; // @ 0x418 + union { + uint32_t value; + struct { + uint32_t sf_aes_key_r2_7 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_key_r2_7; // @ 0x41c + union { + uint32_t value; + struct { + uint32_t sf_aes_iv_r2_w0 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_iv_r2_w0; // @ 0x420 + union { + uint32_t value; + struct { + uint32_t sf_aes_iv_r2_w1 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_iv_r2_w1; // @ 0x424 + union { + uint32_t value; + struct { + uint32_t sf_aes_iv_r2_w2 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_iv_r2_w2; // @ 0x428 + union { + uint32_t value; + struct { + uint32_t sf_aes_iv_r2_w3 : 32; // @ 31 -- 0 # 0x0 + }; + } sf_aes_iv_r2_w3; // @ 0x42c + union { + uint32_t value; + struct { + uint32_t sf_aes_r2_end : 14; // @ 13 -- 0 # 0xffffc000 + uint32_t sf_aes_r2_start : 14; // @ 27 -- 14 # 0xf0003fff + uint32_t pad0 : 1; + uint32_t sf_aes_r2_hw_key_en : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t sf_aes_r2_en : 1; // @ 30 -- 30 # 0xbfffffff + uint32_t sf_aes_r2_lock : 1; // @ 31 -- 31 # 0x7fffffff + }; + } sf_aes_r2; // @ 0x430 + union { + uint32_t value; + struct { + uint32_t sf_id0_offset : 24; // @ 23 -- 0 # 0xff000000 + uint32_t pad0 : 8; + }; + } sf_id0_offset; // @ 0x434 + union { + uint32_t value; + struct { + uint32_t sf_id1_offset : 24; // @ 23 -- 0 # 0xff000000 + uint32_t pad0 : 8; + }; + } sf_id1_offset; // @ 0x438 + }; +} sf_ctrl_regs; +#define SF_CTRL_BASE 0x4000b000 +#define SF_CTRL ((sf_ctrl_regs* volatile)(SF_CTRL_BASE)) \ No newline at end of file diff --git a/src/include/soc/spi.h b/src/include/soc/spi.h new file mode 100644 index 0000000..77d6650 --- /dev/null +++ b/src/include/soc/spi.h @@ -0,0 +1,139 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + union { + uint32_t value; + struct { + uint32_t cr_spi_m_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t cr_spi_s_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t cr_spi_frame_size : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t cr_spi_sclk_pol : 1; // @ 4 -- 4 # 0xffffffef + uint32_t cr_spi_sclk_ph : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t cr_spi_bit_inv : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t cr_spi_byte_inv : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t cr_spi_rxd_ignr_en : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t cr_spi_m_cont_en : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t pad0 : 1; + uint32_t cr_spi_deg_en : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t cr_spi_deg_cnt : 4; // @ 15 -- 12 # 0xffff0fff + uint32_t pad1 : 16; + }; + } spi_config; // @ 0x0 + union { + uint32_t value; + struct { + uint32_t spi_end_int : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t spi_txf_int : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t spi_rxf_int : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t spi_sto_int : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t spi_txu_int : 1; // @ 4 -- 4 # 0xffffffef + uint32_t spi_fer_int : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t pad0 : 2; + uint32_t cr_spi_end_mask : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t cr_spi_txf_mask : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t cr_spi_rxf_mask : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t cr_spi_sto_mask : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t cr_spi_txu_mask : 1; // @ 12 -- 12 # 0xffffefff + uint32_t cr_spi_fer_mask : 1; // @ 13 -- 13 # 0xffffdfff + uint32_t pad1 : 2; + uint32_t cr_spi_end_clr : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t rsvd_17 : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t rsvd_18 : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t cr_spi_sto_clr : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t cr_spi_txu_clr : 1; // @ 20 -- 20 # 0xffefffff + uint32_t rsvd_21 : 1; // @ 21 -- 21 # 0xffdfffff + uint32_t pad2 : 2; + uint32_t cr_spi_end_en : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t cr_spi_txf_en : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t cr_spi_rxf_en : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t cr_spi_sto_en : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t cr_spi_txu_en : 1; // @ 28 -- 28 # 0xefffffff + uint32_t cr_spi_fer_en : 1; // @ 29 -- 29 # 0xdfffffff + uint32_t pad3 : 2; + }; + } spi_int_sts; // @ 0x4 + union { + uint32_t value; + struct { + uint32_t sts_spi_bus_busy : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 31; + }; + } spi_bus_busy; // @ 0x8 + uint8_t pad0[0x4]; + union { + uint32_t value; + struct { + uint32_t cr_spi_prd_s : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t cr_spi_prd_p : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t cr_spi_prd_d_ph_0 : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t cr_spi_prd_d_ph_1 : 8; // @ 31 -- 24 # 0xffffff + }; + } spi_prd_0; // @ 0x10 + union { + uint32_t value; + struct { + uint32_t cr_spi_prd_i : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pad0 : 24; + }; + } spi_prd_1; // @ 0x14 + union { + uint32_t value; + struct { + uint32_t cr_spi_rxd_ignr_p : 5; // @ 4 -- 0 # 0xffffffe0 + uint32_t pad0 : 11; + uint32_t cr_spi_rxd_ignr_s : 5; // @ 20 -- 16 # 0xffe0ffff + uint32_t pad1 : 11; + }; + } spi_rxd_ignr; // @ 0x18 + union { + uint32_t value; + struct { + uint32_t cr_spi_sto_value : 12; // @ 11 -- 0 # 0xfffff000 + uint32_t pad0 : 20; + }; + } spi_sto_value; // @ 0x1c + uint8_t pad1[0x60]; + union { + uint32_t value; + struct { + uint32_t spi_dma_tx_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t spi_dma_rx_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t tx_fifo_clr : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t rx_fifo_clr : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t tx_fifo_overflow : 1; // @ 4 -- 4 # 0xffffffef + uint32_t tx_fifo_underflow : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t rx_fifo_overflow : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t rx_fifo_underflow : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t pad0 : 24; + }; + } spi_fifo_config_0; // @ 0x80 + union { + uint32_t value; + struct { + uint32_t tx_fifo_cnt : 3; // @ 2 -- 0 # 0xfffffff8 + uint32_t pad0 : 5; + uint32_t rx_fifo_cnt : 3; // @ 10 -- 8 # 0xfffff8ff + uint32_t pad1 : 5; + uint32_t tx_fifo_th : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t pad2 : 6; + uint32_t rx_fifo_th : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t pad3 : 6; + }; + } spi_fifo_config_1; // @ 0x84 + union { + uint32_t value; + struct { + uint32_t spi_fifo_wdata : 32; // @ 31 -- 0 # 0x0 + }; + } spi_fifo_wdata; // @ 0x88 + union { + uint32_t value; + struct { + uint32_t spi_fifo_rdata : 32; // @ 31 -- 0 # 0x0 + }; + } spi_fifo_rdata; // @ 0x8c + }; +} spi_regs; +#define SPI_BASE 0x4000a200 +#define SPI ((spi_regs* volatile)(SPI_BASE)) \ No newline at end of file diff --git a/src/include/soc/timer.h b/src/include/soc/timer.h new file mode 100644 index 0000000..bf6d225 --- /dev/null +++ b/src/include/soc/timer.h @@ -0,0 +1,284 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + union { + uint32_t value; + struct { + uint32_t pad0 : 2; + uint32_t cs_1 : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t RESERVED_4 : 1; // @ 4 -- 4 # 0xffffffef + uint32_t cs_2 : 2; // @ 6 -- 5 # 0xffffff9f + uint32_t RESERVED_7 : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t cs_wdt : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t pad1 : 22; + }; + } TCCR; // @ 0x0 + uint8_t pad0[0xc]; + union { + uint32_t value; + struct { + uint32_t tmr : 32; // @ 31 -- 0 # 0x0 + }; + } TMR2_0; // @ 0x10 + union { + uint32_t value; + struct { + uint32_t tmr : 32; // @ 31 -- 0 # 0x0 + }; + } TMR2_1; // @ 0x14 + union { + uint32_t value; + struct { + uint32_t tmr : 32; // @ 31 -- 0 # 0x0 + }; + } TMR2_2; // @ 0x18 + union { + uint32_t value; + struct { + uint32_t tmr : 32; // @ 31 -- 0 # 0x0 + }; + } TMR3_0; // @ 0x1c + union { + uint32_t value; + struct { + uint32_t tmr : 32; // @ 31 -- 0 # 0x0 + }; + } TMR3_1; // @ 0x20 + union { + uint32_t value; + struct { + uint32_t tmr : 32; // @ 31 -- 0 # 0x0 + }; + } TMR3_2; // @ 0x24 + uint8_t pad1[0x4]; + union { + uint32_t value; + struct { + uint32_t tcr : 32; // @ 31 -- 0 # 0x0 + }; + } TCR2; // @ 0x2c + union { + uint32_t value; + struct { + uint32_t tcr3_counter : 32; // @ 31 -- 0 # 0x0 + }; + } TCR3; // @ 0x30 + uint8_t pad2[0x4]; + union { + uint32_t value; + struct { + uint32_t tmsr_0 : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t tmsr_1 : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t tmsr_2 : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 29; + }; + } TMSR2; // @ 0x38 + union { + uint32_t value; + struct { + uint32_t tmsr_0 : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t tmsr_1 : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t tmsr_2 : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 29; + }; + } TMSR3; // @ 0x3c + uint8_t pad3[0x4]; + union { + uint32_t value; + struct { + uint32_t tier_0 : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t tier_1 : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t tier_2 : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 29; + }; + } TIER2; // @ 0x44 + union { + uint32_t value; + struct { + uint32_t tier_0 : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t tier_1 : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t tier_2 : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 29; + }; + } TIER3; // @ 0x48 + uint8_t pad4[0x4]; + union { + uint32_t value; + struct { + uint32_t tplvr : 32; // @ 31 -- 0 # 0x0 + }; + } TPLVR2; // @ 0x50 + union { + uint32_t value; + struct { + uint32_t tplvr : 32; // @ 31 -- 0 # 0x0 + }; + } TPLVR3; // @ 0x54 + uint8_t pad5[0x4]; + union { + uint32_t value; + struct { + uint32_t tplcr : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 30; + }; + } TPLCR2; // @ 0x5c + union { + uint32_t value; + struct { + uint32_t tplcr : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t pad0 : 30; + }; + } TPLCR3; // @ 0x60 + union { + uint32_t value; + struct { + uint32_t we : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t wrie : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t pad0 : 30; + }; + } WMER; // @ 0x64 + union { + uint32_t value; + struct { + uint32_t wmr : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } WMR; // @ 0x68 + union { + uint32_t value; + struct { + uint32_t wvr : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } WVR; // @ 0x6c + union { + uint32_t value; + struct { + uint32_t wts : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 31; + }; + } WSR; // @ 0x70 + uint8_t pad6[0x4]; + union { + uint32_t value; + struct { + uint32_t tclr_0 : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t tclr_1 : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t tclr_2 : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 29; + }; + } TICR2; // @ 0x78 + union { + uint32_t value; + struct { + uint32_t tclr_0 : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t tclr_1 : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t tclr_2 : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 29; + }; + } TICR3; // @ 0x7c + union { + uint32_t value; + struct { + uint32_t wiclr : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 31; + }; + } WICR; // @ 0x80 + union { + uint32_t value; + struct { + uint32_t pad0 : 1; + uint32_t timer2_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t timer3_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad1 : 29; + }; + } TCER; // @ 0x84 + union { + uint32_t value; + struct { + uint32_t pad0 : 1; + uint32_t timer2_mode : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t timer3_mode : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad1 : 29; + }; + } TCMR; // @ 0x88 + uint8_t pad7[0x4]; + union { + uint32_t value; + struct { + uint32_t tilr_0 : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t tilr_1 : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t tilr_2 : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 29; + }; + } TILR2; // @ 0x90 + union { + uint32_t value; + struct { + uint32_t tilr_0 : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t tilr_1 : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t tilr_2 : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 29; + }; + } TILR3; // @ 0x94 + union { + uint32_t value; + struct { + uint32_t wcr : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 31; + }; + } WCR; // @ 0x98 + union { + uint32_t value; + struct { + uint32_t wfar : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } WFAR; // @ 0x9c + union { + uint32_t value; + struct { + uint32_t wsar : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } WSAR; // @ 0xa0 + uint8_t pad8[0x4]; + union { + uint32_t value; + struct { + uint32_t tcvwr : 32; // @ 31 -- 0 # 0x0 + }; + } TCVWR2; // @ 0xa8 + union { + uint32_t value; + struct { + uint32_t tcvwr : 32; // @ 31 -- 0 # 0x0 + }; + } TCVWR3; // @ 0xac + uint8_t pad9[0x4]; + union { + uint32_t value; + struct { + uint32_t tcvsyn2 : 32; // @ 31 -- 0 # 0x0 + }; + } TCVSYN2; // @ 0xb4 + union { + uint32_t value; + struct { + uint32_t tcvsyn3 : 32; // @ 31 -- 0 # 0x0 + }; + } TCVSYN3; // @ 0xb8 + union { + uint32_t value; + struct { + uint32_t pad0 : 8; + uint32_t tcdr2 : 8; // @ 15 -- 8 # 0xffff00ff + uint32_t tcdr3 : 8; // @ 23 -- 16 # 0xff00ffff + uint32_t wcdr : 8; // @ 31 -- 24 # 0xffffff + }; + } TCDR; // @ 0xbc + }; +} timer_regs; +#define TIMER_BASE 0x4000a500 +#define TIMER ((timer_regs* volatile)(TIMER_BASE)) \ No newline at end of file diff --git a/src/include/soc/tzc_nsec.h b/src/include/soc/tzc_nsec.h new file mode 100644 index 0000000..c82efc8 --- /dev/null +++ b/src/include/soc/tzc_nsec.h @@ -0,0 +1,62 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + uint8_t pad0[0x40]; + union { + uint32_t value; + struct { + uint32_t tzc_rom0_r0_id0_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t tzc_rom0_r1_id0_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t tzc_rom1_r0_id0_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t tzc_rom1_r1_id0_en : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pad0 : 4; + uint32_t tzc_rom0_r0_id1_en : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t tzc_rom0_r1_id1_en : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t tzc_rom1_r0_id1_en : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t tzc_rom1_r1_id1_en : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t pad1 : 4; + uint32_t tzc_rom0_r0_en : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t tzc_rom0_r1_en : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t tzc_rom1_r0_en : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t tzc_rom1_r1_en : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t pad2 : 4; + uint32_t tzc_rom0_r0_lock : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t tzc_rom0_r1_lock : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t tzc_rom1_r0_lock : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t tzc_rom1_r1_lock : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t tzc_sboot_done : 4; // @ 31 -- 28 # 0xfffffff + }; + } tzc_rom_ctrl; // @ 0x40 + union { + uint32_t value; + struct { + uint32_t tzc_rom0_r0_end : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t tzc_rom0_r0_start : 16; // @ 31 -- 16 # 0xffff + }; + } tzc_rom0_r0; // @ 0x44 + union { + uint32_t value; + struct { + uint32_t tzc_rom0_r1_end : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t tzc_rom0_r1_start : 16; // @ 31 -- 16 # 0xffff + }; + } tzc_rom0_r1; // @ 0x48 + union { + uint32_t value; + struct { + uint32_t tzc_rom1_r0_end : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t tzc_rom1_r0_start : 16; // @ 31 -- 16 # 0xffff + }; + } tzc_rom1_r0; // @ 0x4c + union { + uint32_t value; + struct { + uint32_t tzc_rom1_r1_end : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t tzc_rom1_r1_start : 16; // @ 31 -- 16 # 0xffff + }; + } tzc_rom1_r1; // @ 0x50 + }; +} tzc_nsec_regs; +#define TZC_NSEC_BASE 0x40006000 +#define TZC_NSEC ((tzc_nsec_regs* volatile)(TZC_NSEC_BASE)) \ No newline at end of file diff --git a/src/include/soc/tzc_sec.h b/src/include/soc/tzc_sec.h new file mode 100644 index 0000000..90582e2 --- /dev/null +++ b/src/include/soc/tzc_sec.h @@ -0,0 +1,62 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + uint8_t pad0[0x40]; + union { + uint32_t value; + struct { + uint32_t tzc_rom0_r0_id0_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t tzc_rom0_r1_id0_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t tzc_rom1_r0_id0_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t tzc_rom1_r1_id0_en : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t pad0 : 4; + uint32_t tzc_rom0_r0_id1_en : 1; // @ 8 -- 8 # 0xfffffeff + uint32_t tzc_rom0_r1_id1_en : 1; // @ 9 -- 9 # 0xfffffdff + uint32_t tzc_rom1_r0_id1_en : 1; // @ 10 -- 10 # 0xfffffbff + uint32_t tzc_rom1_r1_id1_en : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t pad1 : 4; + uint32_t tzc_rom0_r0_en : 1; // @ 16 -- 16 # 0xfffeffff + uint32_t tzc_rom0_r1_en : 1; // @ 17 -- 17 # 0xfffdffff + uint32_t tzc_rom1_r0_en : 1; // @ 18 -- 18 # 0xfffbffff + uint32_t tzc_rom1_r1_en : 1; // @ 19 -- 19 # 0xfff7ffff + uint32_t pad2 : 4; + uint32_t tzc_rom0_r0_lock : 1; // @ 24 -- 24 # 0xfeffffff + uint32_t tzc_rom0_r1_lock : 1; // @ 25 -- 25 # 0xfdffffff + uint32_t tzc_rom1_r0_lock : 1; // @ 26 -- 26 # 0xfbffffff + uint32_t tzc_rom1_r1_lock : 1; // @ 27 -- 27 # 0xf7ffffff + uint32_t tzc_sboot_done : 4; // @ 31 -- 28 # 0xfffffff + }; + } tzc_rom_ctrl; // @ 0x40 + union { + uint32_t value; + struct { + uint32_t tzc_rom0_r0_end : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t tzc_rom0_r0_start : 16; // @ 31 -- 16 # 0xffff + }; + } tzc_rom0_r0; // @ 0x44 + union { + uint32_t value; + struct { + uint32_t tzc_rom0_r1_end : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t tzc_rom0_r1_start : 16; // @ 31 -- 16 # 0xffff + }; + } tzc_rom0_r1; // @ 0x48 + union { + uint32_t value; + struct { + uint32_t tzc_rom1_r0_end : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t tzc_rom1_r0_start : 16; // @ 31 -- 16 # 0xffff + }; + } tzc_rom1_r0; // @ 0x4c + union { + uint32_t value; + struct { + uint32_t tzc_rom1_r1_end : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t tzc_rom1_r1_start : 16; // @ 31 -- 16 # 0xffff + }; + } tzc_rom1_r1; // @ 0x50 + }; +} tzc_sec_regs; +#define TZC_SEC_BASE 0x40005000 +#define TZC_SEC ((tzc_sec_regs* volatile)(TZC_SEC_BASE)) \ No newline at end of file diff --git a/src/include/soc/uart.h b/src/include/soc/uart.h new file mode 100644 index 0000000..c8d2e76 --- /dev/null +++ b/src/include/soc/uart.h @@ -0,0 +1,192 @@ +typedef union { + uint32_t regs[0x400]; + uint8_t pad[0x1000]; + struct { + union { + uint32_t value; + struct { + uint32_t cr_utx_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t cr_utx_cts_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t cr_utx_frm_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t pad0 : 1; + uint32_t cr_utx_prt_en : 1; // @ 4 -- 4 # 0xffffffef + uint32_t cr_utx_prt_sel : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t cr_utx_ir_en : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t cr_utx_ir_inv : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t cr_utx_bit_cnt_d : 3; // @ 10 -- 8 # 0xfffff8ff + uint32_t pad1 : 1; + uint32_t cr_utx_bit_cnt_p : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t pad2 : 2; + uint32_t cr_utx_len : 16; // @ 31 -- 16 # 0xffff + }; + } utx_config; // @ 0x0 + union { + uint32_t value; + struct { + uint32_t cr_urx_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t cr_urx_rts_sw_mode : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t cr_urx_rts_sw_val : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t cr_urx_abr_en : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t cr_urx_prt_en : 1; // @ 4 -- 4 # 0xffffffef + uint32_t cr_urx_prt_sel : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t cr_urx_ir_en : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t cr_urx_ir_inv : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t cr_urx_bit_cnt_d : 3; // @ 10 -- 8 # 0xfffff8ff + uint32_t cr_urx_deg_en : 1; // @ 11 -- 11 # 0xfffff7ff + uint32_t cr_urx_deg_cnt : 4; // @ 15 -- 12 # 0xffff0fff + uint32_t cr_urx_len : 16; // @ 31 -- 16 # 0xffff + }; + } urx_config; // @ 0x4 + union { + uint32_t value; + struct { + uint32_t cr_utx_bit_prd : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t cr_urx_bit_prd : 16; // @ 31 -- 16 # 0xffff + }; + } uart_bit_prd; // @ 0x8 + union { + uint32_t value; + struct { + uint32_t cr_uart_bit_inv : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t pad0 : 31; + }; + } data_config; // @ 0xc + union { + uint32_t value; + struct { + uint32_t cr_utx_ir_pos_s : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t cr_utx_ir_pos_p : 16; // @ 31 -- 16 # 0xffff + }; + } utx_ir_position; // @ 0x10 + union { + uint32_t value; + struct { + uint32_t cr_urx_ir_pos_s : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t pad0 : 16; + }; + } urx_ir_position; // @ 0x14 + union { + uint32_t value; + struct { + uint32_t cr_urx_rto_value : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pad0 : 24; + }; + } urx_rto_timer; // @ 0x18 + uint8_t pad0[0x4]; + union { + uint32_t value; + struct { + uint32_t utx_end_int : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t urx_end_int : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t utx_fifo_int : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t urx_fifo_int : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t urx_rto_int : 1; // @ 4 -- 4 # 0xffffffef + uint32_t urx_pce_int : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t utx_fer_int : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t urx_fer_int : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t pad0 : 24; + }; + } uart_int_sts; // @ 0x20 + union { + uint32_t value; + struct { + uint32_t cr_utx_end_mask : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t cr_urx_end_mask : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t cr_utx_fifo_mask : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t cr_urx_fifo_mask : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t cr_urx_rto_mask : 1; // @ 4 -- 4 # 0xffffffef + uint32_t cr_urx_pce_mask : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t cr_utx_fer_mask : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t cr_urx_fer_mask : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t pad0 : 24; + }; + } uart_int_mask; // @ 0x24 + union { + uint32_t value; + struct { + uint32_t cr_utx_end_clr : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t cr_urx_end_clr : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t rsvd_2 : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t rsvd_3 : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t cr_urx_rto_clr : 1; // @ 4 -- 4 # 0xffffffef + uint32_t cr_urx_pce_clr : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t rsvd_6 : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t rsvd_7 : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t pad0 : 24; + }; + } uart_int_clear; // @ 0x28 + union { + uint32_t value; + struct { + uint32_t cr_utx_end_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t cr_urx_end_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t cr_utx_fifo_en : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t cr_urx_fifo_en : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t cr_urx_rto_en : 1; // @ 4 -- 4 # 0xffffffef + uint32_t cr_urx_pce_en : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t cr_utx_fer_en : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t cr_urx_fer_en : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t pad0 : 24; + }; + } uart_int_en; // @ 0x2c + union { + uint32_t value; + struct { + uint32_t sts_utx_bus_busy : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t sts_urx_bus_busy : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t pad0 : 30; + }; + } uart_status; // @ 0x30 + union { + uint32_t value; + struct { + uint32_t sts_urx_abr_prd_start : 16; // @ 15 -- 0 # 0xffff0000 + uint32_t sts_urx_abr_prd_0x55 : 16; // @ 31 -- 16 # 0xffff + }; + } sts_urx_abr_prd; // @ 0x34 + uint8_t pad1[0x48]; + union { + uint32_t value; + struct { + uint32_t uart_dma_tx_en : 1; // @ 0 -- 0 # 0xfffffffe + uint32_t uart_dma_rx_en : 1; // @ 1 -- 1 # 0xfffffffd + uint32_t tx_fifo_clr : 1; // @ 2 -- 2 # 0xfffffffb + uint32_t rx_fifo_clr : 1; // @ 3 -- 3 # 0xfffffff7 + uint32_t tx_fifo_overflow : 1; // @ 4 -- 4 # 0xffffffef + uint32_t tx_fifo_underflow : 1; // @ 5 -- 5 # 0xffffffdf + uint32_t rx_fifo_overflow : 1; // @ 6 -- 6 # 0xffffffbf + uint32_t rx_fifo_underflow : 1; // @ 7 -- 7 # 0xffffff7f + uint32_t pad0 : 24; + }; + } uart_fifo_config_0; // @ 0x80 + union { + uint32_t value; + struct { + uint32_t tx_fifo_cnt : 6; // @ 5 -- 0 # 0xffffffc0 + uint32_t pad0 : 2; + uint32_t rx_fifo_cnt : 6; // @ 13 -- 8 # 0xffffc0ff + uint32_t pad1 : 2; + uint32_t tx_fifo_th : 5; // @ 20 -- 16 # 0xffe0ffff + uint32_t pad2 : 3; + uint32_t rx_fifo_th : 5; // @ 28 -- 24 # 0xe0ffffff + uint32_t pad3 : 3; + }; + } uart_fifo_config_1; // @ 0x84 + union { + uint32_t value; + struct { + uint32_t uart_fifo_wdata : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pad0 : 24; + }; + } uart_fifo_wdata; // @ 0x88 + union { + uint32_t value; + struct { + uint32_t uart_fifo_rdata : 8; // @ 7 -- 0 # 0xffffff00 + uint32_t pad0 : 24; + }; + } uart_fifo_rdata; // @ 0x8c + }; +} uart_regs; +#define UART_BASE 0x4000a000 +#define UART ((uart_regs* volatile)(UART_BASE)) \ No newline at end of file From 63427a378eeadeb88d6720f2ee47baf9a50f2210 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Thu, 28 Oct 2021 00:44:35 -0500 Subject: [PATCH 058/148] partial link library --- CMakeLists.txt | 4 ++- cmake/add_module.cmake | 49 +++++++++++++++++++++++++++++++++++ src/bl602_wifi/CMakeLists.txt | 31 +++------------------- 3 files changed, 56 insertions(+), 28 deletions(-) create mode 100644 cmake/add_module.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index c5f600a..be544e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,9 +4,11 @@ set(CMAKE_SYSTEM_PROCESSOR riscv) SET(CMAKE_CROSSCOMPILING 1) set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") -add_compile_options(-std=c11 -march=rv32imfc -mabi=ilp32f) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -march=rv32imfc -mabi=ilp32f") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -march=rv32imfc -mabi=ilp32f") project(bl602_re VERSION 0.1.0) include_directories(./src/include) +include(cmake/add_module.cmake) add_subdirectory(./src/bl602_wifi) diff --git a/cmake/add_module.cmake b/cmake/add_module.cmake new file mode 100644 index 0000000..1b53c9f --- /dev/null +++ b/cmake/add_module.cmake @@ -0,0 +1,49 @@ + +function (init_bl602module libname) + set(libname "${libname}" PARENT_SCOPE) + add_library(${libname} STATIC) + target_include_directories(${libname} PRIVATE ${CMAKE_SOURCE_DIR}/src/include/${libname}) +endfunction() + +function (add_bl602module module_name) + file(GLOB lSRCs + "${CMAKE_CURRENT_LIST_DIR}/${module_name}/*.c" + ) + get_property(gSrcs GLOBAL PROPERTY ${libname}_SRCs) + list(APPEND gSrcs ${lSRCs}) + set_property(GLOBAL PROPERTY ${libname}_SRCs "${gSrcs}") + + get_property(NEEDREMOVE GLOBAL PROPERTY ${libname}_NEEDREMOVE) + foreach(blsrc ${lSRCs}) + get_filename_component(wle ${blsrc} NAME_WLE) + list(APPEND NEEDREMOVE ${wle}) + endforeach() + + set_property(GLOBAL PROPERTY ${libname}_NEEDREMOVE "${NEEDREMOVE}") +endfunction() + +function (end_bl602module) + file(GLOB original_OBJs + "${PROJECT_SOURCE_DIR}/lib${libname}/*.o" + ) + + foreach(blobj ${original_OBJs}) + get_filename_component(wle ${blobj} NAME_WLE) + list(APPEND OBJs ${wle}) + endforeach() + + get_property(NEEDREMOVE GLOBAL PROPERTY ${libname}_NEEDREMOVE) + list(REMOVE_ITEM OBJs ${NEEDREMOVE}) + list(TRANSFORM OBJs PREPEND "${PROJECT_SOURCE_DIR}/lib${libname}/") + list(TRANSFORM OBJs APPEND ".o") + set_property(GLOBAL PROPERTY ${libname}_OBJs "${OBJs}") + + get_property(gSrcs GLOBAL PROPERTY ${libname}_SRCs) + target_sources(${libname} PRIVATE ${gSrcs} ${OBJs}) + + message(STATUS "Library info: ${libname}") + message(STATUS "Using Srcs") + message(STATUS "${gSrcs}") + message(STATUS "Using Objs") + message(STATUS "${OBJs}") +endfunction() \ No newline at end of file diff --git a/src/bl602_wifi/CMakeLists.txt b/src/bl602_wifi/CMakeLists.txt index 3a5e008..2dbb21e 100644 --- a/src/bl602_wifi/CMakeLists.txt +++ b/src/bl602_wifi/CMakeLists.txt @@ -1,27 +1,4 @@ - - -file(GLOB bl602_wifi_original_OBJs -"${PROJECT_SOURCE_DIR}/libbl602_wifi/*.o" -) - -file(GLOB bl602_wifi_SRCs -"*.c" -) - -foreach(blsrc ${bl602_wifi_SRCs}) - get_filename_component(wle ${blsrc} NAME_WLE) - list(APPEND NEEDREMOVE ${wle}) -endforeach() - -foreach(blobj ${bl602_wifi_original_OBJs}) - get_filename_component(wle ${blobj} NAME_WLE) - list(APPEND bl602_wifi_OBJs ${wle}) -endforeach() - -list(REMOVE_ITEM bl602_wifi_OBJs ${NEEDREMOVE}) -list(TRANSFORM bl602_wifi_OBJs PREPEND "${PROJECT_SOURCE_DIR}/libbl602_wifi/") -list(TRANSFORM bl602_wifi_OBJs APPEND ".o") - - -add_library(bl602_wifi STATIC ${bl602_wifi_SRCs} ${bl602_wifi_OBJs}) - +init_bl602module("bl602_wifi") +add_bl602module("driver/phy/phy_rf") +add_bl602module("driver/phyif") +end_bl602module() \ No newline at end of file From ad0421491eedc27c5a547b86340bcde402a9b861 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Thu, 28 Oct 2021 00:45:26 -0500 Subject: [PATCH 059/148] reg scanner --- blobs/reg_riu.h | 902 ++++++++++++++++++++++++++++ blobs/regdump_44C0B000-44C0CFFF.bin | Bin 0 -> 8192 bytes script/reg.py | 65 ++ 3 files changed, 967 insertions(+) create mode 100644 blobs/reg_riu.h create mode 100644 blobs/regdump_44C0B000-44C0CFFF.bin create mode 100755 script/reg.py diff --git a/blobs/reg_riu.h b/blobs/reg_riu.h new file mode 100644 index 0000000..36c326b --- /dev/null +++ b/blobs/reg_riu.h @@ -0,0 +1,902 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright(c) 2019-2021, Celeno Communications Ltd. */ + +#ifndef CL_REG_RIU_H +#define CL_REG_RIU_H + +#include +#include "reg/reg_access.h" +#include "hw.h" + +#define RIU_RSF_FILE_SIZE 0x60C + +/* + * @brief CCA_CNT_CS register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 CCA_CNT_CS                0x0
+ * 
+ */ +#define RIU_CCA_CNT_CS_ADDR (REG_RIU_BASE_ADDR + 0x00000058) +#define RIU_CCA_CNT_CS_OFFSET 0x00000058 +#define RIU_CCA_CNT_CS_INDEX 0x00000016 +#define RIU_CCA_CNT_CS_RESET 0x00000000 + +static inline u32 riu_cca_cnt_cs_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_CCA_CNT_CS_ADDR); +} + +/* + * @brief RSF_CONTROL register definition + * resampling filter operation mode register description + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31    rsf_init_en               1
+ *    07    rsf_tx_bypass_type        0
+ *    06    rsf_tx_bypass_mode        1
+ *    05    rsf_rx_bypass_type        0
+ *    04    rsf_rx_bypass_mode        1
+ *    01    rsf_rx_ctl_from_reg       1
+ * 
+ */ +#define RIU_RSF_CONTROL_ADDR (REG_RIU_BASE_ADDR + 0x000001A8) +#define RIU_RSF_CONTROL_OFFSET 0x000001A8 +#define RIU_RSF_CONTROL_INDEX 0x0000006A +#define RIU_RSF_CONTROL_RESET 0x80000053 + +static inline void riu_rsf_control_rsf_init_en_setf(struct cl_hw *cl_hw, u8 rsfiniten) +{ + cl_reg_write(cl_hw, RIU_RSF_CONTROL_ADDR, + (cl_reg_read(cl_hw, RIU_RSF_CONTROL_ADDR) & ~((u32)0x80000000)) | ((u32)rsfiniten << 31)); +} + +/* + * @brief RSF_INIT register definition + * resampling filter initialization data register description + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 RSF_INIT_DATA             0x0
+ * 
+ */ +#define RIU_RSF_INIT_ADDR (REG_RIU_BASE_ADDR + 0x000001AC) +#define RIU_RSF_INIT_OFFSET 0x000001AC +#define RIU_RSF_INIT_INDEX 0x0000006B +#define RIU_RSF_INIT_RESET 0x00000000 + +static inline void riu_rsf_init_set(struct cl_hw *cl_hw, u32 value) +{ + cl_reg_write(cl_hw, RIU_RSF_INIT_ADDR, value); +} + +/* + * @brief AGCFSM_RAM_INIT_1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31    AGC_FSM_RAM_INIT_EN       0
+ *    29    AGC_FSM_RAM_INIT_AINC2    0
+ *    28    AGC_FSM_RAM_INIT_AINC1    0
+ *    12    AGC_FSM_RAM_INIT_WPTR_SET 0
+ *    10:00 AGC_FSM_RAM_INIT_WPTR     0x0
+ * 
+ */ +#define RIU_AGCFSM_RAM_INIT_1_ADDR (REG_RIU_BASE_ADDR + 0x000001B0) +#define RIU_AGCFSM_RAM_INIT_1_OFFSET 0x000001B0 +#define RIU_AGCFSM_RAM_INIT_1_INDEX 0x0000006C +#define RIU_AGCFSM_RAM_INIT_1_RESET 0x00000000 + +static inline void riu_agcfsm_ram_init_1_agc_fsm_ram_init_wptr_setf(struct cl_hw *cl_hw, + u16 agcfsmraminitwptr) +{ + ASSERT_ERR((((u32)agcfsmraminitwptr << 0) & ~((u32)0x000007FF)) == 0); + cl_reg_write(cl_hw, RIU_AGCFSM_RAM_INIT_1_ADDR, + (cl_reg_read(cl_hw, RIU_AGCFSM_RAM_INIT_1_ADDR) & ~((u32)0x000007FF)) | ((u32)agcfsmraminitwptr << 0)); +} + +static inline void riu_agcfsm_ram_init_1_agc_fsm_ram_init_wptr_set_setf(struct cl_hw *cl_hw, u8 agcfsmraminitwptrset) +{ + ASSERT_ERR((((u32)agcfsmraminitwptrset << 12) & ~((u32)0x00001000)) == 0); + cl_reg_write(cl_hw, RIU_AGCFSM_RAM_INIT_1_ADDR, + (cl_reg_read(cl_hw, RIU_AGCFSM_RAM_INIT_1_ADDR) & ~((u32)0x00001000)) | ((u32)agcfsmraminitwptrset << 12)); +} + +static inline void riu_agcfsm_ram_init_1_agc_fsm_ram_init_ainc_1_setf(struct cl_hw *cl_hw, + u8 agcfsmraminitainc1) +{ + ASSERT_ERR((((u32)agcfsmraminitainc1 << 28) & ~((u32)0x10000000)) == 0); + cl_reg_write(cl_hw, RIU_AGCFSM_RAM_INIT_1_ADDR, + (cl_reg_read(cl_hw, RIU_AGCFSM_RAM_INIT_1_ADDR) & ~((u32)0x10000000)) | ((u32)agcfsmraminitainc1 << 28)); +} + +static inline void riu_agcfsm_ram_init_1_agc_fsm_ram_init_en_setf(struct cl_hw *cl_hw, + u8 agcfsmraminiten) +{ + cl_reg_write(cl_hw, RIU_AGCFSM_RAM_INIT_1_ADDR, + (cl_reg_read(cl_hw, RIU_AGCFSM_RAM_INIT_1_ADDR) & ~((u32)0x80000000)) | ((u32)agcfsmraminiten << 31)); +} + +/* + * @brief AGCFSM_RAM_INIT_2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 AGC_FSM_RAM_INIT_WDATA    0x0
+ * 
+ */ +#define RIU_AGCFSM_RAM_INIT_2_ADDR (REG_RIU_BASE_ADDR + 0x000001B4) +#define RIU_AGCFSM_RAM_INIT_2_OFFSET 0x000001B4 +#define RIU_AGCFSM_RAM_INIT_2_INDEX 0x0000006D +#define RIU_AGCFSM_RAM_INIT_2_RESET 0x00000000 + +static inline void riu_agcfsm_ram_init_2_set(struct cl_hw *cl_hw, u32 value) +{ + cl_reg_write(cl_hw, RIU_AGCFSM_RAM_INIT_2_ADDR, value); +} + +/* + * @brief AGCINBDPOW_20_STAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:24 INBDPOW20_PDBM3           0x0
+ *    23:16 INBDPOW20_PDBM2           0x0
+ *    15:08 INBDPOW20_PDBM1           0x0
+ *    07:00 INBDPOW20_PDBM0           0x0
+ * 
+ */ +#define RIU_AGCINBDPOW_20_STAT_ADDR (REG_RIU_BASE_ADDR + 0x0000020C) +#define RIU_AGCINBDPOW_20_STAT_OFFSET 0x0000020C +#define RIU_AGCINBDPOW_20_STAT_INDEX 0x00000083 +#define RIU_AGCINBDPOW_20_STAT_RESET 0x00000000 + +static inline void riu_agcinbdpow_20_stat_unpack(struct cl_hw *cl_hw, + u8 *inbdpow20pdbm3, u8 *inbdpow20pdbm2, + u8 *inbdpow20pdbm1, u8 *inbdpow20pdbm0) +{ + u32 local_val = cl_reg_read(cl_hw, RIU_AGCINBDPOW_20_STAT_ADDR); + + *inbdpow20pdbm3 = (local_val & ((u32)0xFF000000)) >> 24; + *inbdpow20pdbm2 = (local_val & ((u32)0x00FF0000)) >> 16; + *inbdpow20pdbm1 = (local_val & ((u32)0x0000FF00)) >> 8; + *inbdpow20pdbm0 = (local_val & ((u32)0x000000FF)) >> 0; +} + +/* + * @brief AGCINBDPOW_20_PNOISESTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:24 INBDPOW20_PNOISEDBM3      0x0
+ *    23:16 INBDPOW20_PNOISEDBM2      0x0
+ *    15:08 INBDPOW20_PNOISEDBM1      0x0
+ *    07:00 INBDPOW20_PNOISEDBM0      0x0
+ * 
+ */ +#define RIU_AGCINBDPOW_20_PNOISESTAT_ADDR (REG_RIU_BASE_ADDR + 0x00000228) +#define RIU_AGCINBDPOW_20_PNOISESTAT_OFFSET 0x00000228 +#define RIU_AGCINBDPOW_20_PNOISESTAT_INDEX 0x0000008A +#define RIU_AGCINBDPOW_20_PNOISESTAT_RESET 0x00000000 + +static inline u32 riu_agcinbdpow_20_pnoisestat_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_AGCINBDPOW_20_PNOISESTAT_ADDR); +} + +/* + * @brief AGCINBDPOWSECNOISESTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    23:16 INBDPOW80_SNOISEDBM       0x0
+ *    15:08 INBDPOW40_SNOISEDBM       0x0
+ *    07:00 INBDPOW20_SNOISEDBM       0x0
+ * 
+ */ +#define RIU_AGCINBDPOWSECNOISESTAT_ADDR (REG_RIU_BASE_ADDR + 0x00000230) +#define RIU_AGCINBDPOWSECNOISESTAT_OFFSET 0x00000230 +#define RIU_AGCINBDPOWSECNOISESTAT_INDEX 0x0000008C +#define RIU_AGCINBDPOWSECNOISESTAT_RESET 0x00000000 + +static inline u32 riu_agcinbdpowsecnoisestat_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_AGCINBDPOWSECNOISESTAT_ADDR); +} + +/* + * @brief CCA_CNT_MODEM_STATE_P register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 CCA_CNT_MODEM_STATE_P     0x0
+ * 
+ */ +#define RIU_CCA_CNT_MODEM_STATE_P_ADDR (REG_RIU_BASE_ADDR + 0x000002DC) +#define RIU_CCA_CNT_MODEM_STATE_P_OFFSET 0x000002DC +#define RIU_CCA_CNT_MODEM_STATE_P_INDEX 0x000000B7 +#define RIU_CCA_CNT_MODEM_STATE_P_RESET 0x00000000 + +static inline u32 riu_cca_cnt_modem_state_p_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_CCA_CNT_MODEM_STATE_P_ADDR); +} + +/* + * @brief CCA_CNT_MODEM_STATE_20_S register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 CCA_CNT_MODEM_STATE_20_S  0x0
+ * 
+ */ +#define RIU_CCA_CNT_MODEM_STATE_20_S_ADDR (REG_RIU_BASE_ADDR + 0x000002E0) +#define RIU_CCA_CNT_MODEM_STATE_20_S_OFFSET 0x000002E0 +#define RIU_CCA_CNT_MODEM_STATE_20_S_INDEX 0x000000B8 +#define RIU_CCA_CNT_MODEM_STATE_20_S_RESET 0x00000000 + +static inline u32 riu_cca_cnt_modem_state_20_s_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_CCA_CNT_MODEM_STATE_20_S_ADDR); +} + +/* + * @brief CCA_CNT_MODEM_STATE_40_S register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 CCA_CNT_MODEM_STATE_40_S  0x0
+ * 
+ */ +#define RIU_CCA_CNT_MODEM_STATE_40_S_ADDR (REG_RIU_BASE_ADDR + 0x000002E4) +#define RIU_CCA_CNT_MODEM_STATE_40_S_OFFSET 0x000002E4 +#define RIU_CCA_CNT_MODEM_STATE_40_S_INDEX 0x000000B9 +#define RIU_CCA_CNT_MODEM_STATE_40_S_RESET 0x00000000 + +static inline u32 riu_cca_cnt_modem_state_40_s_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_CCA_CNT_MODEM_STATE_40_S_ADDR); +} + +/* + * @brief CCA_CNT_MODEM_STATE_80_S register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 CCA_CNT_MODEM_STATE_80_S  0x0
+ * 
+ */ +#define RIU_CCA_CNT_MODEM_STATE_80_S_ADDR (REG_RIU_BASE_ADDR + 0x000002E8) +#define RIU_CCA_CNT_MODEM_STATE_80_S_OFFSET 0x000002E8 +#define RIU_CCA_CNT_MODEM_STATE_80_S_INDEX 0x000000BA +#define RIU_CCA_CNT_MODEM_STATE_80_S_RESET 0x00000000 + +static inline u32 riu_cca_cnt_modem_state_80_s_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_CCA_CNT_MODEM_STATE_80_S_ADDR); +} + +/* + * @brief CCA_CNT_ENERGY_THR_P register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 CCA_CNT_ENERGY_THR_P      0x0
+ * 
+ */ +#define RIU_CCA_CNT_ENERGY_THR_P_ADDR (REG_RIU_BASE_ADDR + 0x000002F4) +#define RIU_CCA_CNT_ENERGY_THR_P_OFFSET 0x000002F4 +#define RIU_CCA_CNT_ENERGY_THR_P_INDEX 0x000000BD +#define RIU_CCA_CNT_ENERGY_THR_P_RESET 0x00000000 + +static inline u32 riu_cca_cnt_energy_thr_p_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_CCA_CNT_ENERGY_THR_P_ADDR); +} + +/* + * @brief CCA_CNT_ENERGY_THR_20_S register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 CCA_CNT_ENERGY_THR_20_S   0x0
+ * 
+ */ +#define RIU_CCA_CNT_ENERGY_THR_20_S_ADDR (REG_RIU_BASE_ADDR + 0x000002F8) +#define RIU_CCA_CNT_ENERGY_THR_20_S_OFFSET 0x000002F8 +#define RIU_CCA_CNT_ENERGY_THR_20_S_INDEX 0x000000BE +#define RIU_CCA_CNT_ENERGY_THR_20_S_RESET 0x00000000 + +static inline u32 riu_cca_cnt_energy_thr_20_s_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_CCA_CNT_ENERGY_THR_20_S_ADDR); +} + +/* + * @brief CCA_CNT_GI_20_P register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 CCA_CNT_GI_20_P           0x0
+ * 
+ */ +#define RIU_CCA_CNT_GI_20_P_ADDR (REG_RIU_BASE_ADDR + 0x000002FC) +#define RIU_CCA_CNT_GI_20_P_OFFSET 0x000002FC +#define RIU_CCA_CNT_GI_20_P_INDEX 0x000000BF +#define RIU_CCA_CNT_GI_20_P_RESET 0x00000000 + +static inline u32 riu_cca_cnt_gi_20_p_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_CCA_CNT_GI_20_P_ADDR); +} + +/* + * @brief RWNXAGCRAMP register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    26:24 RAMPDNNDLINDEX            0x5
+ *    23:16 RAMPDNGAPQDB              0x20
+ *    10:08 RAMPUPNDLINDEX            0x7
+ *    07:00 RAMPUPGAPQDB              0x10
+ * 
+ */ +#define RIU_RWNXAGCRAMP_ADDR (REG_RIU_BASE_ADDR + 0x0000036C) +#define RIU_RWNXAGCRAMP_OFFSET 0x0000036C +#define RIU_RWNXAGCRAMP_INDEX 0x000000DB +#define RIU_RWNXAGCRAMP_RESET 0x05200710 + +static inline u8 riu_rwnxagcramp_rampupgapqdb_getf(struct cl_hw *cl_hw) +{ + u32 local_val = cl_reg_read(cl_hw, RIU_RWNXAGCRAMP_ADDR); + + return ((local_val & ((u32)0x000000FF)) >> 0); +} + +static inline void riu_rwnxagcramp_rampupgapqdb_setf(struct cl_hw *cl_hw, u8 rampupgapqdb) +{ + cl_reg_write(cl_hw, RIU_RWNXAGCRAMP_ADDR, + (cl_reg_read(cl_hw, RIU_RWNXAGCRAMP_ADDR) & ~((u32)0x000000FF)) | ((u32)rampupgapqdb << 0)); +} + +/* + * @brief RWNXAGCCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:26 COMBPATHSEL               0x3F
+ *    25:20 GAINKEEP                  0x0
+ *    16    HTSTFGAINEN               1
+ *    15    NOISE_CAPTURE_DELAY_MODE  0
+ *    14    EST_PATH_SEL_2            0
+ *    13    CCA_MDM_ST_CLEAR          0
+ *    12    AGCFSMRESET               0
+ *    11    RADARDETEN                0
+ *    10    RIFSDETEN                 1
+ *    09    DSSSONLY                  0
+ *    08    OFDMONLY                  0
+ *    07:04 GPSTATUS                  0x0
+ *    03    EST_PATH_SEL              0
+ *    01    ADC_SEL_RADAR_DETECTOR    0
+ *    00    ADC_SEL_COMP_MODULE       0
+ * 
+ */ +#define RIU_RWNXAGCCNTL_ADDR (REG_RIU_BASE_ADDR + 0x00000390) +#define RIU_RWNXAGCCNTL_OFFSET 0x00000390 +#define RIU_RWNXAGCCNTL_INDEX 0x000000E4 +#define RIU_RWNXAGCCNTL_RESET 0xFC010400 + +static inline void riu_rwnxagccntl_agcfsmreset_setf(struct cl_hw *cl_hw, u8 agcfsmreset) +{ + ASSERT_ERR((((u32)agcfsmreset << 12) & ~((u32)0x00001000)) == 0); + cl_reg_write(cl_hw, RIU_RWNXAGCCNTL_ADDR, + (cl_reg_read(cl_hw, RIU_RWNXAGCCNTL_ADDR) & ~((u32)0x00001000)) | ((u32)agcfsmreset << 12)); +} + +/* + * @brief RWNXAGCCCA_1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31    CCA_CNT_CLEAR             0
+ *    30:29 CCA_CNT_RATE              0x0
+ *    28:20 INBDCCAPOWMINDBM          0x1B5
+ *    19:12 CCAFALLTHRDBM             0xBF
+ *    10    CCAEnergy_Reset_Type      0
+ *    09    DISCCAEN                  1
+ *    08    SATCCAEN                  1
+ *    07:00 CCARISETHRDBM             0xC2
+ * 
+ */ +#define RIU_RWNXAGCCCA_1_ADDR (REG_RIU_BASE_ADDR + 0x000003AC) +#define RIU_RWNXAGCCCA_1_OFFSET 0x000003AC +#define RIU_RWNXAGCCCA_1_INDEX 0x000000EB +#define RIU_RWNXAGCCCA_1_RESET 0x1B5BF3C2 + +static inline void riu_rwnxagccca_1_cca_cnt_clear_setf(struct cl_hw *cl_hw, u8 ccacntclear) +{ + cl_reg_write(cl_hw, RIU_RWNXAGCCCA_1_ADDR, + (cl_reg_read(cl_hw, RIU_RWNXAGCCCA_1_ADDR) & ~((u32)0x80000000)) | ((u32)ccacntclear << 31)); +} + +/* + * @brief RWNXAGCCCACTRL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:28 CCAFLAG3_CTRL             0xA
+ *    27:24 CCAFLAG2_CTRL             0x2
+ *    23:20 CCAFLAG1_CTRL             0x8
+ *    19:16 CCAFLAG0_CTRL             0x0
+ *    14:12 CCA_SECOND_ANT_SEL        0x1
+ *    10:08 CCA_MAIN_ANT_SEL          0x0
+ *    07:04 CCADEMOD                  0xF
+ *    00    CCACSEN                   1
+ * 
+ */ +#define RIU_RWNXAGCCCACTRL_ADDR (REG_RIU_BASE_ADDR + 0x000003B0) +#define RIU_RWNXAGCCCACTRL_OFFSET 0x000003B0 +#define RIU_RWNXAGCCCACTRL_INDEX 0x000000EC +#define RIU_RWNXAGCCCACTRL_RESET 0xA28010F1 + +static inline void riu_rwnxagcccactrl_cca_main_ant_sel_setf(struct cl_hw *cl_hw, u8 ccamainantsel) +{ + ASSERT_ERR((((u32)ccamainantsel << 8) & ~((u32)0x00000700)) == 0); + cl_reg_write(cl_hw, RIU_RWNXAGCCCACTRL_ADDR, + (cl_reg_read(cl_hw, RIU_RWNXAGCCCACTRL_ADDR) & ~((u32)0x00000700)) | ((u32)ccamainantsel << 8)); +} + +/* + * @brief RWNXAGCCCASTATE_0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    28    CCAMDMSTFORCEEN           0
+ *    27:24 CCAMDMSTFORCE             0x0
+ *    23:12 RXSTATECCA20_SSEL         0x380
+ *    11:00 RXSTATECCA20_PSEL         0x3F8
+ * 
+ */ +#define RIU_RWNXAGCCCASTATE_0_ADDR (REG_RIU_BASE_ADDR + 0x000003B4) +#define RIU_RWNXAGCCCASTATE_0_OFFSET 0x000003B4 +#define RIU_RWNXAGCCCASTATE_0_INDEX 0x000000ED +#define RIU_RWNXAGCCCASTATE_0_RESET 0x003803F8 + +static inline void riu_rwnxagcccastate_0_rxstatecca_20_psel_setf(struct cl_hw *cl_hw, + u16 rxstatecca20psel) +{ + ASSERT_ERR((((u32)rxstatecca20psel << 0) & ~((u32)0x00000FFF)) == 0); + cl_reg_write(cl_hw, RIU_RWNXAGCCCASTATE_0_ADDR, + (cl_reg_read(cl_hw, RIU_RWNXAGCCCASTATE_0_ADDR) & ~((u32)0x00000FFF)) | ((u32)rxstatecca20psel << 0)); +} + +/* + * @brief AGCINBDPOWNOISEPER_20_STAT_0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:24 INBDPOWNOISEDBMPER20_3    0x0
+ *    23:16 INBDPOWNOISEDBMPER20_2    0x0
+ *    15:08 INBDPOWNOISEDBMPER20_1    0x0
+ *    07:00 INBDPOWNOISEDBMPER20_0    0x0
+ * 
+ */ +#define RIU_AGCINBDPOWNOISEPER_20_STAT_0_ADDR (REG_RIU_BASE_ADDR + 0x00000478) +#define RIU_AGCINBDPOWNOISEPER_20_STAT_0_OFFSET 0x00000478 +#define RIU_AGCINBDPOWNOISEPER_20_STAT_0_INDEX 0x0000011E +#define RIU_AGCINBDPOWNOISEPER_20_STAT_0_RESET 0x00000000 + +static inline u32 riu_agcinbdpownoiseper_20_stat_0_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_AGCINBDPOWNOISEPER_20_STAT_0_ADDR); +} + +/* + * @brief AGCINBDPOWNOISEPER_20_STAT_1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:24 INBDPOWNOISEDBMPER20_7    0x0
+ *    23:16 INBDPOWNOISEDBMPER20_6    0x0
+ *    15:08 INBDPOWNOISEDBMPER20_5    0x0
+ *    07:00 INBDPOWNOISEDBMPER20_4    0x0
+ * 
+ */ +#define RIU_AGCINBDPOWNOISEPER_20_STAT_1_ADDR (REG_RIU_BASE_ADDR + 0x0000047C) +#define RIU_AGCINBDPOWNOISEPER_20_STAT_1_OFFSET 0x0000047C +#define RIU_AGCINBDPOWNOISEPER_20_STAT_1_INDEX 0x0000011F +#define RIU_AGCINBDPOWNOISEPER_20_STAT_1_RESET 0x00000000 + +static inline u32 riu_agcinbdpownoiseper_20_stat_1_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_AGCINBDPOWNOISEPER_20_STAT_1_ADDR); +} + +/* + * @brief INBDPOWFORMAC_0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:24 INBDPOW20_PDBMA3_MAC      0x0
+ *    23:16 INBDPOW20_PDBMA2_MAC      0x0
+ *    15:08 INBDPOW20_PDBMA1_MAC      0x0
+ *    07:00 INBDPOW20_PDBMA0_MAC      0x0
+ * 
+ */ +#define RIU_INBDPOWFORMAC_0_ADDR (REG_RIU_BASE_ADDR + 0x00000480) +#define RIU_INBDPOWFORMAC_0_OFFSET 0x00000480 +#define RIU_INBDPOWFORMAC_0_INDEX 0x00000120 +#define RIU_INBDPOWFORMAC_0_RESET 0x00000000 + +static inline u32 riu_inbdpowformac_0_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_INBDPOWFORMAC_0_ADDR); +} + +/* + * @brief INBDPOWFORMAC_1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    15:08 INBDPOW20_PDBMA5_MAC      0x0
+ *    07:00 INBDPOW20_PDBMA4_MAC      0x0
+ * 
+ */ +#define RIU_INBDPOWFORMAC_1_ADDR (REG_RIU_BASE_ADDR + 0x00000484) +#define RIU_INBDPOWFORMAC_1_OFFSET 0x00000484 +#define RIU_INBDPOWFORMAC_1_INDEX 0x00000121 +#define RIU_INBDPOWFORMAC_1_RESET 0x00000000 + +static inline u32 riu_inbdpowformac_1_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_INBDPOWFORMAC_1_ADDR); +} + +/* + * @brief INBDPOWFORMAC_2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    23:16 INBDPOW80_SDBM_MAC        0x0
+ *    15:08 INBDPOW40_SDBM_MAC        0x0
+ *    07:00 INBDPOW20_SDBM_MAC        0x0
+ * 
+ */ +#define RIU_INBDPOWFORMAC_2_ADDR (REG_RIU_BASE_ADDR + 0x00000488) +#define RIU_INBDPOWFORMAC_2_OFFSET 0x00000488 +#define RIU_INBDPOWFORMAC_2_INDEX 0x00000122 +#define RIU_INBDPOWFORMAC_2_RESET 0x00000000 + +static inline u32 riu_inbdpowformac_2_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_INBDPOWFORMAC_2_ADDR); +} + +/* + * @brief INBDPOWFORMAC_3 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:24 INBDPOWPER20_PDBM_3_MAC   0x0
+ *    23:16 INBDPOWPER20_PDBM_2_MAC   0x0
+ *    15:08 INBDPOWPER20_PDBM_1_MAC   0x0
+ *    07:00 INBDPOWPER20_PDBM_0_MAC   0x0
+ * 
+ */ +#define RIU_INBDPOWFORMAC_3_ADDR (REG_RIU_BASE_ADDR + 0x0000048C) +#define RIU_INBDPOWFORMAC_3_OFFSET 0x0000048C +#define RIU_INBDPOWFORMAC_3_INDEX 0x00000123 +#define RIU_INBDPOWFORMAC_3_RESET 0x00000000 + +static inline u32 riu_inbdpowformac_3_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_INBDPOWFORMAC_3_ADDR); +} + +/* + * @brief INBDPOWFORMAC_4 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:24 INBDPOWPER20_PDBM_7_MAC   0x0
+ *    23:16 INBDPOWPER20_PDBM_6_MAC   0x0
+ *    15:08 INBDPOWPER20_PDBM_5_MAC   0x0
+ *    07:00 INBDPOWPER20_PDBM_4_MAC   0x0
+ * 
+ */ +#define RIU_INBDPOWFORMAC_4_ADDR (REG_RIU_BASE_ADDR + 0x00000490) +#define RIU_INBDPOWFORMAC_4_OFFSET 0x00000490 +#define RIU_INBDPOWFORMAC_4_INDEX 0x00000124 +#define RIU_INBDPOWFORMAC_4_RESET 0x00000000 + +static inline u32 riu_inbdpowformac_4_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_INBDPOWFORMAC_4_ADDR); +} + +/* + * @brief CCA_CNT_GI_20_S register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 CCA_CNT_GI_20_S           0x0
+ * 
+ */ +#define RIU_CCA_CNT_GI_20_S_ADDR (REG_RIU_BASE_ADDR + 0x00000494) +#define RIU_CCA_CNT_GI_20_S_OFFSET 0x00000494 +#define RIU_CCA_CNT_GI_20_S_INDEX 0x00000125 +#define RIU_CCA_CNT_GI_20_S_RESET 0x00000000 + +static inline u32 riu_cca_cnt_gi_20_s_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_CCA_CNT_GI_20_S_ADDR); +} + +/* + * @brief CCA_CNT_GI_40_S register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 CCA_CNT_GI_40_S           0x0
+ * 
+ */ +#define RIU_CCA_CNT_GI_40_S_ADDR (REG_RIU_BASE_ADDR + 0x00000498) +#define RIU_CCA_CNT_GI_40_S_OFFSET 0x00000498 +#define RIU_CCA_CNT_GI_40_S_INDEX 0x00000126 +#define RIU_CCA_CNT_GI_40_S_RESET 0x00000000 + +static inline u32 riu_cca_cnt_gi_40_s_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_CCA_CNT_GI_40_S_ADDR); +} + +/* + * @brief CCA_CNT_GI_80_S register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 CCA_CNT_GI_80_S           0x0
+ * 
+ */ +#define RIU_CCA_CNT_GI_80_S_ADDR (REG_RIU_BASE_ADDR + 0x0000049C) +#define RIU_CCA_CNT_GI_80_S_OFFSET 0x0000049C +#define RIU_CCA_CNT_GI_80_S_INDEX 0x00000127 +#define RIU_CCA_CNT_GI_80_S_RESET 0x00000000 + +static inline u32 riu_cca_cnt_gi_80_s_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_CCA_CNT_GI_80_S_ADDR); +} + +/* + * @brief CCA_CNT_ENERGY_THR_40_S register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 CCA_CNT_ENERGY_THR_40_S   0x0
+ * 
+ */ +#define RIU_CCA_CNT_ENERGY_THR_40_S_ADDR (REG_RIU_BASE_ADDR + 0x000004A0) +#define RIU_CCA_CNT_ENERGY_THR_40_S_OFFSET 0x000004A0 +#define RIU_CCA_CNT_ENERGY_THR_40_S_INDEX 0x00000128 +#define RIU_CCA_CNT_ENERGY_THR_40_S_RESET 0x00000000 + +static inline u32 riu_cca_cnt_energy_thr_40_s_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_CCA_CNT_ENERGY_THR_40_S_ADDR); +} + +/* + * @brief CCA_CNT_ENERGY_THR_80_S register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 CCA_CNT_ENERGY_THR_80_S   0x0
+ * 
+ */ +#define RIU_CCA_CNT_ENERGY_THR_80_S_ADDR (REG_RIU_BASE_ADDR + 0x000004A4) +#define RIU_CCA_CNT_ENERGY_THR_80_S_OFFSET 0x000004A4 +#define RIU_CCA_CNT_ENERGY_THR_80_S_INDEX 0x00000129 +#define RIU_CCA_CNT_ENERGY_THR_80_S_RESET 0x00000000 + +static inline u32 riu_cca_cnt_energy_thr_80_s_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_CCA_CNT_ENERGY_THR_80_S_ADDR); +} + +/* + * @brief CCA_CNT_ENERGY_THR_20_BAND_0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 CCA_CNT_ENERGY_THR_20_BAND_0 0x0
+ * 
+ */ +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_0_ADDR (REG_RIU_BASE_ADDR + 0x000004A8) +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_0_OFFSET 0x000004A8 +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_0_INDEX 0x0000012A +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_0_RESET 0x00000000 + +static inline u32 riu_cca_cnt_energy_thr_20_band_0_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_CCA_CNT_ENERGY_THR_20_BAND_0_ADDR); +} + +/* + * @brief CCA_CNT_ENERGY_THR_20_BAND_1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 CCA_CNT_ENERGY_THR_20_BAND_1 0x0
+ * 
+ */ +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_1_ADDR (REG_RIU_BASE_ADDR + 0x000004AC) +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_1_OFFSET 0x000004AC +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_1_INDEX 0x0000012B +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_1_RESET 0x00000000 + +static inline u32 riu_cca_cnt_energy_thr_20_band_1_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_CCA_CNT_ENERGY_THR_20_BAND_1_ADDR); +} + +/* + * @brief CCA_CNT_ENERGY_THR_20_BAND_2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 CCA_CNT_ENERGY_THR_20_BAND_2 0x0
+ * 
+ */ +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_2_ADDR (REG_RIU_BASE_ADDR + 0x000004B0) +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_2_OFFSET 0x000004B0 +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_2_INDEX 0x0000012C +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_2_RESET 0x00000000 + +static inline u32 riu_cca_cnt_energy_thr_20_band_2_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_CCA_CNT_ENERGY_THR_20_BAND_2_ADDR); +} + +/* + * @brief CCA_CNT_ENERGY_THR_20_BAND_3 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 CCA_CNT_ENERGY_THR_20_BAND_3 0x0
+ * 
+ */ +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_3_ADDR (REG_RIU_BASE_ADDR + 0x000004B4) +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_3_OFFSET 0x000004B4 +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_3_INDEX 0x0000012D +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_3_RESET 0x00000000 + +static inline u32 riu_cca_cnt_energy_thr_20_band_3_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_CCA_CNT_ENERGY_THR_20_BAND_3_ADDR); +} + +/* + * @brief CCA_CNT_ENERGY_THR_20_BAND_4 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 CCA_CNT_ENERGY_THR_20_BAND_4 0x0
+ * 
+ */ +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_4_ADDR (REG_RIU_BASE_ADDR + 0x000004B8) +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_4_OFFSET 0x000004B8 +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_4_INDEX 0x0000012E +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_4_RESET 0x00000000 + +static inline u32 riu_cca_cnt_energy_thr_20_band_4_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_CCA_CNT_ENERGY_THR_20_BAND_4_ADDR); +} + +/* + * @brief CCA_CNT_ENERGY_THR_20_BAND_5 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 CCA_CNT_ENERGY_THR_20_BAND_5 0x0
+ * 
+ */ +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_5_ADDR (REG_RIU_BASE_ADDR + 0x000004BC) +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_5_OFFSET 0x000004BC +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_5_INDEX 0x0000012F +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_5_RESET 0x00000000 + +static inline u32 riu_cca_cnt_energy_thr_20_band_5_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_CCA_CNT_ENERGY_THR_20_BAND_5_ADDR); +} + +/* + * @brief CCA_CNT_ENERGY_THR_20_BAND_6 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 CCA_CNT_ENERGY_THR_20_BAND_6 0x0
+ * 
+ */ +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_6_ADDR (REG_RIU_BASE_ADDR + 0x000004C0) +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_6_OFFSET 0x000004C0 +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_6_INDEX 0x00000130 +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_6_RESET 0x00000000 + +static inline u32 riu_cca_cnt_energy_thr_20_band_6_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_CCA_CNT_ENERGY_THR_20_BAND_6_ADDR); +} + +/* + * @brief CCA_CNT_ENERGY_THR_20_BAND_7 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:00 CCA_CNT_ENERGY_THR_20_BAND_7 0x0
+ * 
+ */ +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_7_ADDR (REG_RIU_BASE_ADDR + 0x000004C4) +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_7_OFFSET 0x000004C4 +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_7_INDEX 0x00000131 +#define RIU_CCA_CNT_ENERGY_THR_20_BAND_7_RESET 0x00000000 + +static inline u32 riu_cca_cnt_energy_thr_20_band_7_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_CCA_CNT_ENERGY_THR_20_BAND_7_ADDR); +} + +/* + * @brief AGCADCPOWSTAT_2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:24 INBDPOW20_PDBM5           0x0
+ *    23:16 INBDPOW20_PDBM4           0x0
+ *    14:08 ADCPOWDBV5                0x0
+ *    06:00 ADCPOWDBV4                0x0
+ * 
+ */ +#define RIU_AGCADCPOWSTAT_2_ADDR (REG_RIU_BASE_ADDR + 0x00000670) +#define RIU_AGCADCPOWSTAT_2_OFFSET 0x00000670 +#define RIU_AGCADCPOWSTAT_2_INDEX 0x0000019C +#define RIU_AGCADCPOWSTAT_2_RESET 0x00000000 + +static inline void riu_agcadcpowstat_2_unpack(struct cl_hw *cl_hw, + u8 *inbdpow20pdbm5, u8 *inbdpow20pdbm4, + u8 *adcpowdbv5, u8 *adcpowdbv4) +{ + u32 local_val = cl_reg_read(cl_hw, RIU_AGCADCPOWSTAT_2_ADDR); + + *inbdpow20pdbm5 = (local_val & ((u32)0xFF000000)) >> 24; + *inbdpow20pdbm4 = (local_val & ((u32)0x00FF0000)) >> 16; + *adcpowdbv5 = (local_val & ((u32)0x00007F00)) >> 8; + *adcpowdbv4 = (local_val & ((u32)0x0000007F)) >> 0; +} + +/* + * @brief AGCINBDPOW_20_PNOISESTAT_2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *    31:24 INBDPOW20_PNOISEDBM5      0x0
+ *    23:16 INBDPOW20_PNOISEDBM4      0x0
+ *    15:08 ADCPOWDBM5                0x0
+ *    07:00 ADCPOWDBM4                0x0
+ * 
+ */ +#define RIU_AGCINBDPOW_20_PNOISESTAT_2_ADDR (REG_RIU_BASE_ADDR + 0x0000067C) +#define RIU_AGCINBDPOW_20_PNOISESTAT_2_OFFSET 0x0000067C +#define RIU_AGCINBDPOW_20_PNOISESTAT_2_INDEX 0x0000019F +#define RIU_AGCINBDPOW_20_PNOISESTAT_2_RESET 0x00000000 + +static inline u32 riu_agcinbdpow_20_pnoisestat_2_get(struct cl_hw *cl_hw) +{ + return cl_reg_read(cl_hw, RIU_AGCINBDPOW_20_PNOISESTAT_2_ADDR); +} + +#endif /*_REG_RIU_H_ */ \ No newline at end of file diff --git a/blobs/regdump_44C0B000-44C0CFFF.bin b/blobs/regdump_44C0B000-44C0CFFF.bin new file mode 100644 index 0000000000000000000000000000000000000000..b82bd3689ab3322a6ba506c779381cdfc479d362 GIT binary patch literal 8192 zcmWf1+`=%Dfr5ep0|+y)07C(U844I4nM_gvu@GWl-Y79#L%@l_iCnL-v$8NTLNyEU za&xjWGcz#)1r%hZB}4@H`M5Y37%VMpI69g%7zEfASUH$OI2c3(g_#(bfHFYRrQkQK z3qv5siQ-W14(1eQ7NF*>KX@4CKn$J3@R^&LnSp_mGnC=b=V zb1-b(prNsE|Lwa_CxEFP0o>9cj4U?F#vTF!0^m%KU2;@(Gz5lu2ndeW|D*N)Fi+zI zy*FC_6AYr^s$jJKAFeSw>MvqKKme*p(U64!gp&=_7!nxN7y=kr;TWVO0EmGd79d!_ zAO)rw7??rbriOzVPzk6gX_Sztl!BVJp}8$-+J=p46-5~_0WM%Ka@hE2)FY!IFd71* zAut*OLm>qCA(cAJsR|%Q2aJbCAGyTO!0Yni4--h7k)c5WSo?#p1cL#C2T+KE2iBSZ ia)uOOV*n2L3k@kJk2-cV1V%$(Gz3ONU^E0M2mt`52T)}I literal 0 HcmV?d00001 diff --git a/script/reg.py b/script/reg.py new file mode 100755 index 0000000..ebf1e86 --- /dev/null +++ b/script/reg.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +def RegFromComment2(comment:str): + import re + field_pattern = r'\*\s+(\d\d)(:(\d\d))*\s*([^\s]+)\s+(.*)' + + field_matches = re.finditer(field_pattern, comment) + + for g in field_matches: + fname = g.group(4) + msb = int(g.group(1)) + lsb = g.group(3) + val = g.group(5) + if val.startswith("0x"): + val = int(val, 16) + else: + val = int(val) + if not lsb: + lsb = msb + else: + lsb = int(lsb) + yield fname, msb, lsb, val + + +def getregs(fname, pattern='name'): + import re + state = "idle" + regs = [] + if pattern == 'name': + name_pattern = r'\* @(name) ([^\s]+)' + else: + name_pattern = r'\* @(brief) ([^\s]+)' + addr_pattern = r'#define .*_OFFSET\s+0x([0-9A-F]+)' + name = '' + for i in open(fname).readlines(): + if state == "idle": + g = re.search(name_pattern, i) + if g: + name = g.group(2) + regs.append(i) + state = "find_reg" + elif state == "find_reg": + g = re.search(addr_pattern, i) + if g: + yield name, "".join(regs), int(g.group(1), 16) & 0xFFFFF + regs.clear() + state = "idle" + else: + regs.append(i) + + +binfile = open("../blobs/regdump_44C0B000-44C0CFFF.bin", "rb").read(0x2000) + + +import struct +for rname, r, offset in getregs('../blobs/reg_riu.h', pattern='brief'): + regdefault = binfile[offset:offset+4] + print(regdefault) + regdefault = int.from_bytes(regdefault, byteorder='little') + matched = True + print(f"Reg {rname}, val {regdefault} offset {hex(offset)}") + for name, msb, lsb, val in RegFromComment2(r): + vreset = (regdefault >> lsb) & ((2**(msb - lsb+1) - 1)) + print(f"\t{name}, expected {hex(val)}, get {hex(vreset)}") + if vreset != val: + matched = False From 9f91b711557aa1934339a659ab7960d71e309eee Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Thu, 28 Oct 2021 00:47:10 -0500 Subject: [PATCH 060/148] preliminary decompiled code --- .../driver/phy/phy_rf/bl602_rf_calib_data.c | 10 + .../driver/phy/phy_rf/bl602_rf_private.c | 1727 +++++++++++++++++ src/bl602_wifi/driver/phy/phy_rf/macro.h | 47 + .../{ => driver/phy/phy_rf}/phy_adapt.c | 10 +- .../{ => driver/phy/phy_rf}/phy_bl602.c | 151 +- .../{ => driver/phy/phy_rf}/phy_hal.c | 2 +- .../{ => driver/phy/phy_rf}/phy_helper.c | 2 +- .../{ => driver/phy/phy_rf}/phy_tcal.c | 14 +- .../{ => driver/phy/phy_rf}/phy_trpc.c | 8 +- src/bl602_wifi/{ => driver/phy/phy_rf}/rf.c | 12 +- .../driver/phy/phy_rf/rf_private_save.h | 29 + src/bl602_wifi/driver/phy/phy_rf/rfc_bl602.c | 784 ++++++++ .../{ => driver/phyif}/phyif_utils.c | 2 +- src/bl602_wifi/phy.h | 8 - src/bl602_wifi/rfc_bl602.c | 169 -- src/bl602_wifi/rfc_bl602.h | 9 - src/{bl602_wifi => include}/assert.h | 0 .../bl602_wifi/phy_rf/bl602_rf_calib_data.h | 58 + .../bl602_wifi/phy_rf}/bl602_rf_private.h | 77 +- .../bl602_wifi/phy_rf}/hal_desc.h | 13 +- src/include/bl602_wifi/phy_rf/phy.h | 74 + .../bl602_wifi/phy_rf}/phy_adapt.h | 2 +- .../bl602_wifi/phy_rf}/phy_bl602.h | 36 +- .../bl602_wifi/phy_rf}/phy_hal.h | 0 .../bl602_wifi/phy_rf}/phy_helper.h | 0 .../bl602_wifi/phy_rf}/phy_tcal.h | 0 .../bl602_wifi/phy_rf}/phy_trpc.h | 0 .../bl602_wifi/phy_rf}/rf.h | 0 src/include/bl602_wifi/phy_rf/rfc_bl602.h | 199 ++ .../bl602_wifi/phyif}/phyif_utils.h | 0 src/{bl602_wifi => include}/utils.h | 2 +- 31 files changed, 3161 insertions(+), 284 deletions(-) create mode 100644 src/bl602_wifi/driver/phy/phy_rf/bl602_rf_calib_data.c create mode 100644 src/bl602_wifi/driver/phy/phy_rf/bl602_rf_private.c create mode 100644 src/bl602_wifi/driver/phy/phy_rf/macro.h rename src/bl602_wifi/{ => driver/phy/phy_rf}/phy_adapt.c (97%) rename src/bl602_wifi/{ => driver/phy/phy_rf}/phy_bl602.c (74%) rename src/bl602_wifi/{ => driver/phy/phy_rf}/phy_hal.c (97%) rename src/bl602_wifi/{ => driver/phy/phy_rf}/phy_helper.c (99%) rename src/bl602_wifi/{ => driver/phy/phy_rf}/phy_tcal.c (87%) rename src/bl602_wifi/{ => driver/phy/phy_rf}/phy_trpc.c (96%) rename src/bl602_wifi/{ => driver/phy/phy_rf}/rf.c (52%) create mode 100644 src/bl602_wifi/driver/phy/phy_rf/rf_private_save.h create mode 100644 src/bl602_wifi/driver/phy/phy_rf/rfc_bl602.c rename src/bl602_wifi/{ => driver/phyif}/phyif_utils.c (98%) delete mode 100644 src/bl602_wifi/phy.h delete mode 100644 src/bl602_wifi/rfc_bl602.c delete mode 100644 src/bl602_wifi/rfc_bl602.h rename src/{bl602_wifi => include}/assert.h (100%) create mode 100644 src/include/bl602_wifi/phy_rf/bl602_rf_calib_data.h rename src/{bl602_wifi => include/bl602_wifi/phy_rf}/bl602_rf_private.h (62%) rename src/{bl602_wifi => include/bl602_wifi/phy_rf}/hal_desc.h (91%) create mode 100644 src/include/bl602_wifi/phy_rf/phy.h rename src/{bl602_wifi => include/bl602_wifi/phy_rf}/phy_adapt.h (98%) rename src/{bl602_wifi => include/bl602_wifi/phy_rf}/phy_bl602.h (87%) rename src/{bl602_wifi => include/bl602_wifi/phy_rf}/phy_hal.h (100%) rename src/{bl602_wifi => include/bl602_wifi/phy_rf}/phy_helper.h (100%) rename src/{bl602_wifi => include/bl602_wifi/phy_rf}/phy_tcal.h (100%) rename src/{bl602_wifi => include/bl602_wifi/phy_rf}/phy_trpc.h (100%) rename src/{bl602_wifi => include/bl602_wifi/phy_rf}/rf.h (100%) create mode 100644 src/include/bl602_wifi/phy_rf/rfc_bl602.h rename src/{bl602_wifi => include/bl602_wifi/phyif}/phyif_utils.h (100%) rename src/{bl602_wifi => include}/utils.h (90%) diff --git a/src/bl602_wifi/driver/phy/phy_rf/bl602_rf_calib_data.c b/src/bl602_wifi/driver/phy/phy_rf/bl602_rf_calib_data.c new file mode 100644 index 0000000..db68925 --- /dev/null +++ b/src/bl602_wifi/driver/phy/phy_rf/bl602_rf_calib_data.c @@ -0,0 +1,10 @@ +#include + +#if 0 +#define RF_CALIB_DATA_ADDR (0x40020000) + +rf_calib_data_tag* rf_calib_data = (rf_calib_data_tag *)RF_CALIB_DATA_ADDR; +#else +static rf_calib_data_tag data = {0}; +rf_calib_data_tag* rf_calib_data = &data; +#endif \ No newline at end of file diff --git a/src/bl602_wifi/driver/phy/phy_rf/bl602_rf_private.c b/src/bl602_wifi/driver/phy/phy_rf/bl602_rf_private.c new file mode 100644 index 0000000..1d42423 --- /dev/null +++ b/src/bl602_wifi/driver/phy/phy_rf/bl602_rf_private.c @@ -0,0 +1,1727 @@ +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#define kHz *1000 +#define MHz *1000*1000 +#define NUM_CHANNELS (21) +#define NUM_WIFI_CHANNELS (14) + +static uint32_t channel_div_table[21] = { + 0x14088889, 0x14111111, 0x1419999A, 0x14222222, + 0x142AAAAB, 0x14333333, 0x143BBBBC, 0x14444444, + 0x144CCCCD, 0x14555555, 0x145DDDDE, 0x14666666, + 0x146EEEEF, 0x14777777, 0x14800000, 0x14888889, + 0x14911111, 0x1499999A, 0x14A22222, 0x14AAAAAB, + 0x14B33333 +}; + +static uint16_t channel_cnt_table[21] = { + 0xA6EB, 0xA732, 0xA779, 0xA7C0, + 0xA808, 0xA84F, 0xA896, 0xA8DD, + 0xA924, 0xA96B, 0xA9B2, 0xA9F9, + 0xAA40, 0xAA87, 0xAACF, 0xAB16, + 0xAB5D, 0xABA4, 0xABEB, 0xAC32, + 0xAC79 +}; + +static uint16_t fcal_div = 0x855; + +static tx_pwr_index data; +tx_pwr_index* tp_index = &data; + +void rf_pri_config_bandwidth(uint32_t bw) { + RF->rbb3.rbb_bw = bw; +} + +static uint16_t channel_cnt_range[3] = { + 0xA6A0, 0xA6E0, 0xACE0 +}; + +static uint16_t channel_cw_table[21]; +static uint16_t channel_cnt_opt_table[40]; + +// meas = measure? +uint16_t rf_pri_fcal_meas(uint32_t cw) { + RF->vco1.lo_vco_freq_cw = cw; + BL602_Delay_US(100); + RF->vco4.fcal_cnt_start = 1; + do { + if (RF->vco4.fcal_cnt_rdy) break; + } while (1); + uint16_t fcal_meas = RF->vco3.fcal_cnt_op; + RF->vco4.fcal_cnt_start = 0; + return fcal_meas; +} + +typedef struct { +#define RF_PRI_SAVE(field) uint32_t field; +#include "rf_private_save.h" +} rf_state_save_t; + +static rf_state_save_t rf_state; + +static void rf_pri_save_state_for_cal() { +#define RF_PRI_SAVE(field) rf_state.field = RF->field.value; +#include "rf_private_save.h" +} + + +static void rf_pri_restore_state_for_cal() { +#define RF_PRI_SAVE(field) RF->field.value = rf_state.field; +#include "rf_private_save.h" +} + +#include "macro.h" +#define mapper0(x) new_pucr1.x = 0; +#define mapper1(x) new_pucr1.x = 1; +#define P_CLR(...) APPLY(mapper0, __VA_ARGS__) +#define P_SET(...) APPLY(mapper1, __VA_ARGS__) + +static void rf_pri_manu_pu(uint32_t mode) { + RF->rf_fsm_ctrl_hw.rf_fsm_ctrl_en = 0; + RF->rfctrl_hw_en.value = 0; + + __typeof__ (((rf_regs* )(RF_BASE))->pucr1) new_pucr1 = RF->pucr1; + + switch (mode) { + case E_RF_MODE_RCCAL: + P_CLR(pu_lna, pu_rmxgm, pu_rmx, pu_pkdet, + pu_pwrmx, pu_pa, pu_tmx, pu_tbb, + pu_rxbuf, pu_txbuf, pu_tosdac); + P_SET(pu_osmx, pu_pfd, pu_fbdv, pu_vco, + pu_rbb, pu_adc, adc_clk_en, pu_rosdac, + pu_dac, trsw_en); + break; + case E_RF_MODE_TXCAL: + P_CLR(pu_lna, pu_rmxgm, pu_rmx, pu_pkdet, pu_rosdac, pu_rxbuf); + P_SET(pu_txbuf, trsw_en, pu_tosdac, pu_osmx, + pu_pfd, pu_fbdv, pu_vco, pu_rbb, + pu_adc, adc_clk_en, pu_pwrmx, pu_pa, + pu_tmx, pu_tbb, pu_dac); + break; + + case E_RF_MODE_LO_ACAL: + case E_RF_MODE_LO_FCAL: + P_CLR(pu_lna, pu_rmxgm, pu_rmx, pu_tosdac, + pu_rbb, pu_adc, adc_clk_en, pu_pkdet, + pu_rosdac ,pu_pwrmx, pu_pa, pu_tmx, + pu_tbb,pu_dac,pu_rxbuf,pu_txbuf, + trsw_en); + P_SET(pu_osmx, pu_pfd, pu_fbdv, pu_vco); + break; + // in the leak code, this function treat + // 0...2 + default cases with the same code as 6...7 code + // however, in the binary, it uses the same logic + // as case 3 for 0...2 + default cases + // this branch should never touched unless mode == 3 + // so the 0...2 and default should never be used. + // that is why an error is added here. + default: + case E_RF_MODE_IDLE ... E_RF_MODE_RX: + printf("unexpected values for rf_pri_manu_pu\r\n"); + case E_RF_MODE_ROSCAL: + P_CLR(pu_lna, pu_pkdet, pu_pwrmx, pu_pa, + pu_tmx, pu_tbb, pu_dac, pu_txbuf, + pu_tosdac); + P_SET(pu_osmx, pu_pfd, pu_fbdv, pu_vco, + pu_rmxgm, pu_rmx, pu_rbb, pu_adc, + adc_clk_en, pu_rxbuf, trsw_en, pu_rosdac); + break; + } + RF->pucr1 = new_pucr1; +} + +static void rf_pri_config_mode(uint32_t mode) { + rf_pri_manu_pu(mode); +} + +#undef P_SET +#undef P_CLR +#undef mapper0 +#undef mapper1 + + +void rf_pri_fcal(void) { + RF->rfcal_status.fcal_status = 0x1; + + rf_pri_save_state_for_cal(); // TBI + rf_pri_config_mode(E_RF_MODE_LO_FCAL); // TBI + + RF->rfcal_ctrlen.fcal_en = 1; + + RF->vco1.lo_vco_freq_cw = 0x80; + RF->fbdv.lo_fbdv_sel_fb_clk = 0; + RF->vco3.fcal_div = fcal_div; + // frequency counter counts # RF periods within a counter + // clock cycle fcal_div is a divider for the counter clock. + + RF->sdm2.value = 0x1000000; + RF->sdm1.lo_sdm_bypass = 1; + + RF->sdm1.lo_sdm_rstb = 0; + RF->fbdv.lo_fbdv_rst = 1; + + BL602_Delay_US(10); + + RF->sdm1.lo_sdm_rstb = 1; + RF->fbdv.lo_fbdv_rst = 0; + + BL602_Delay_US(50); + + RF->vco2.lo_vco_vbias_cw = 2; + + BL602_Delay_US(50); + + uint16_t c0 = (uint16_t)channel_cnt_range[0]; + uint16_t c1 = (uint32_t)channel_cnt_range[1]; + uint16_t c2 = (uint16_t)channel_cnt_range[2]; + + uint16_t cw = 0x80; + while (1) { + for (int j = 6; j >= 0; j--) { + if (rf_pri_fcal_meas(cw) < c0) { + cw -= (1 << j); + } else { + if (rf_pri_fcal_meas(cw) > c1) { + cw += (1 << j); + } else break; + } + } + + if (cw >= 15) + break; + + printf("Unexpected cw %ld\r\n", cw); + + /// reset + RF->sdm1.lo_sdm_rstb = 0; + RF->fbdv.lo_fbdv_rst = 1; + BL602_Delay_US(0x32); + RF->sdm1.lo_sdm_rstb = 1; + RF->fbdv.lo_fbdv_rst = 0; + BL602_Delay_US(0x32); + } + + cw++; + channel_cnt_opt_table[0] = rf_pri_fcal_meas(cw); + + for (int i = 1; i < 40; i++) { + uint16_t cnt = rf_pri_fcal_meas(cw-i); + channel_cnt_opt_table[i] = cnt; + if (cnt > c2) break; + } + + for (int i = 0, j = 0; i < 21; i++) { + while (channel_cnt_opt_table[j] < channel_cnt_table[i]) j++; + channel_cw_table[i] = cw - (j - 1); /// hmmm what if j = 0?\ + /// or it can't because cw was + 1.. + if (j > 0) j--; + } + + rf_pri_restore_state_for_cal(); + + for (int i = 0; i < 21; i++) { + rf_calib_data->lo[i].fcal = channel_cw_table[i]; + printf("%ldth channel,lo_vco_freq_cw=%ld\r\n", i + 1, (uint32_t)(channel_cw_table[i])); + } + + RF->rfcal_status.fcal_status = 3; // 0b11 +} + +void rf_pri_start_rxdfe() { + PACK(RF->rfif_dfe_ctrl0, rfif_dfe_ctrl0) { + rfif_dfe_ctrl0.rx_dfe_en_4s_en = 0; + rfif_dfe_ctrl0.rx_dfe_en_4s = 0; + } + + PACK(RF->rfif_dfe_ctrl0, rfif_dfe_ctrl0) { + rfif_dfe_ctrl0.rfckg_rxclk_4s_on = 1; + rfif_dfe_ctrl0.rx_dfe_en_4s = 1; + rfif_dfe_ctrl0.rx_dfe_en_4s_en = 1; + } +} + +// TODO: verify me +void rf_pri_start_txdfe() { + PACK(RF->rfif_dfe_ctrl0, rfif_dfe_ctrl0) { + rfif_dfe_ctrl0.tx_dfe_en_4s_en = 0; + rfif_dfe_ctrl0.tx_dfe_en_4s = 0; + } + + PACK(RF->rfif_dfe_ctrl0, rfif_dfe_ctrl0) { + rfif_dfe_ctrl0.rfckg_txclk_4s_on = 1; + rfif_dfe_ctrl0.tx_test_sel = 2; + rfif_dfe_ctrl0.tx_dfe_en_4s = 1; + } + + RF->rfif_dfe_ctrl0.tx_dfe_en_4s_en = 1; +} + +static void rf_pri_config_channel(uint32_t channel_index) { + // sdm = sigma-delta modulator ? + PACK(RF->vco1, vco1) { + vco1.lo_vco_freq_cw = rf_calib_data->lo[channel_index].fcal; + vco1.lo_vco_idac_cw = rf_calib_data->lo[channel_index].acal; + } + RF->lodist.lo_osmx_cap = rf_calib_data->lo[channel_index].fcal >> 4; + RF->sdm2.lo_sdmin = channel_div_table[channel_index]; + RF->sdm1.lo_sdm_bypass = 0; + + while (1) { + RF->fbdv.lo_fbdv_rst = 1; + BL602_Delay_US(10); + + RF->fbdv.lo_fbdv_rst = 0; + BL602_Delay_US(50); + + RF->pfdcp.lo_pfd_rst_csd = 1; + BL602_Delay_US(10); + + RF->pfdcp.lo_pfd_rst_csd = 0; + BL602_Delay_US(50); + + __typeof__ (((rf_regs* )(RF_BASE))->lo) mylo = RF->lo; + + if (mylo.lo_slipped_dn || mylo.lo_slipped_up) { + printf("."); + } else { + printf("LO locked %ld %ld\r\n", channel_index, (uint32_t)rf_calib_data->lo[channel_index].fcal); + break; + } + } +} + +static int32_t rf_pri_pm_pwr_avg(uint32_t iq, uint32_t acc_len) { + PACK(RF->dfe_ctrl_6, dfe_ctrl_6) { + RF->dfe_ctrl_6.rx_pm_en = 0; + RF->dfe_ctrl_6.rx_pm_freqshift_en = 0; + } + //RF->dfe_ctrl_6.value &= 0xdfefffff; + RF->dfe_ctrl_7.rx_pm_acc_len = acc_len; + + RF->dfe_ctrl_6.rx_pm_en = 1; + + for (; !(RF->dfe_ctrl_6.rx_pm_done);); + + int32_t iqacc = 0; + if (iq) { + // iq = 1 => i + iqacc = RF->dfe_ctrl_8.rx_pm_iqacc_i; + } else { + // iq = 0 => q + iqacc = RF->dfe_ctrl_9.rx_pm_iqacc_q; + } + iqacc = (iqacc << 7) >> 7; + //RF->dfe_ctrl_6.value &= 0xdfefffff; + PACK(RF->dfe_ctrl_6, dfe_ctrl_6) { + RF->dfe_ctrl_6.rx_pm_en = 0; + RF->dfe_ctrl_6.rx_pm_freqshift_en = 0; + } + return iqacc; +} + +static void rf_pri_roscal_config(uint32_t iq,uint32_t rosdac) { + uint32_t tmpVal = 0; + if (iq) { + RF->rbb1.rosdac_i = rosdac; + } else { + RF->rbb1.rosdac_q = rosdac; + } +} + +static uint32_t rf_pri_roscal_iq(uint32_t iq, uint32_t sram_start_addr, uint32_t length) { + uint32_t rosdac = 0; + for (int i = 5; i >= 0; i--) { + uint32_t uvar7 = rosdac + (1 << i); + rf_pri_roscal_config(iq, uvar7); + if (rf_pri_pm_pwr_avg(iq, 1024) < 1) // leak code says <= 0? + rosdac = uvar7; + } + + uint8_t seq_pattern = 0; + + for (int i = 0; i < 63; i++) { + rf_pri_roscal_config(iq, rosdac); + int32_t pwr = rf_pri_pm_pwr_avg(iq, 1024); + if (pwr < 1) { + seq_pattern = (seq_pattern << 1) & 0xf; + rosdac++; + } else { + seq_pattern = ((seq_pattern << 1) + 1) & 0xf; + rosdac--; + } + if ((seq_pattern == 0b1010) || (seq_pattern == 0b0101)) + break; + } + + return rosdac; +} + +void rf_pri_roscal() { + if (RF->rfcal_stateen.roscal_sten == 0) { + RF->rfcal_status.ros_status = 0; + return ; + } + + RF->rfcal_status.ros_status = 1; + // td + rf_pri_save_state_for_cal(); + rf_pri_config_mode(E_RF_MODE_ROSCAL); + RF->rfcal_ctrlen.roscal_en = 1; + + rf_pri_config_channel(3); // in the leak source the value here is 9. + + RF->trx_gain1.gc_rbb2 = 6; + RF->trx_gain1.gc_rbb1 = 3; + + uint32_t rosdac = rf_pri_roscal_iq(1, 0 /* unused */, 0 /* unused */); + + rf_calib_data->rxcal[3].rosdac_i = rosdac; + + RF->rosdac_ctrl_hw2.rosdac_i_gc3 = rosdac; + printf("rosdac_i_gc3=%ld\r\n", rosdac); + + rf_calib_data->rxcal[2].rosdac_i = rosdac; + + RF->rosdac_ctrl_hw2.rosdac_i_gc2 = rosdac; + printf("rosdac_i_gc2=%ld\r\n", rosdac); + + rf_calib_data->rxcal[1].rosdac_i = rosdac; + + RF->rosdac_ctrl_hw1.rosdac_i_gc1 = rosdac; + printf("rosdac_i_gc1=%ld\r\n", rosdac); + + rf_calib_data->rxcal[0].rosdac_i = rosdac; + + RF->rosdac_ctrl_hw1.rosdac_i_gc0 = rosdac; + printf("rosdac_i_gc0=%ld\r\n", rosdac); + + rosdac = rf_pri_roscal_iq(0, 0 /* unused */, 0 /* unused */); + + rf_calib_data->rxcal[3].rosdac_q = rosdac; + + RF->rosdac_ctrl_hw2.rosdac_q_gc3 = rosdac; + printf("rosdac_q_gc3=%ld\r\n", rosdac); + + rf_calib_data->rxcal[2].rosdac_q = rosdac; + + RF->rosdac_ctrl_hw2.rosdac_q_gc2 = rosdac; + printf("rosdac_q_gc2=%ld\r\n", rosdac); + + rf_calib_data->rxcal[1].rosdac_q = rosdac; + + RF->rosdac_ctrl_hw1.rosdac_q_gc1 = rosdac; + printf("rosdac_q_gc1=%ld\r\n", rosdac); + + rf_calib_data->rxcal[0].rosdac_q = rosdac; + + RF->rosdac_ctrl_hw1.rosdac_q_gc0 = rosdac; + printf("rosdac_q_gc0=%ld\r\n", rosdac); + + rf_pri_restore_state_for_cal(); + + RF->rfcal_status.ros_status = 3; +} + +void rf_pri_full_cal(void) { + // dfe + rf_pri_start_rxdfe(); + rf_pri_start_txdfe(); + rf_pri_fcal(); + rf_pri_lo_acal(); + rf_pri_roscal(); + rf_pri_rccal(); + rf_pri_txcal(); + + PACK(RF->rfctrl_hw_en, rfctrl_hw_en) { + rfctrl_hw_en.rx_gain_ctrl_hw = 1; + rfctrl_hw_en.tx_gain_ctrl_hw = 1; + } + + PACK(RF->rfif_dfe_ctrl0, rfif_dfe_ctrl0) { + rfif_dfe_ctrl0.rfckg_rxclk_4s_on = 0; + rfif_dfe_ctrl0.rx_dfe_en_4s_en = 0; + rfif_dfe_ctrl0.rx_dfe_en_4s = 0; + } + + PACK(RF->rfif_dfe_ctrl0, rfif_dfe_ctrl0) { + rfif_dfe_ctrl0.rfckg_txclk_4s_on = 0; + rfif_dfe_ctrl0.tx_dfe_en_4s_en = 0; + rfif_dfe_ctrl0.tx_dfe_en_4s = 0; + rfif_dfe_ctrl0.tx_test_sel = 0; + } +} +static int32_t rx_notch_para[14][2] = { + {0,0}, {0,0}, {0,0}, {0,0}, + {1,8 MHz}, + {1,3 MHz}, + {1,-2 MHz}, + {1,-7 MHz}, + {0,0}, {0,0}, {0,0}, {0,0}, + {1,8 MHz}, + {1,-4 MHz}, +}; + +void rf_pri_get_notch_param(uint32_t chanfreq_MHz, uint8_t * ncf_on, int32_t * ncf_freq_Hz) { + uint32_t channel_id; + channel_id = 13; + if (chanfreq_MHz < 2473) { + channel_id = (chanfreq_MHz - 2412) / 5; + } + + *ncf_on = (uint8_t)rx_notch_para[channel_id][0]; + *ncf_freq_Hz = rx_notch_para[channel_id][1]; +} + +uint32_t rf_pri_get_vco_freq_cw(uint32_t chanfreq_MHz) { + int32_t a = (int32_t)((chanfreq_MHz-2404)/4 + 0.5); + a = a < 0 ? 0 : a; + if (a > NUM_CHANNELS - 1) + a = NUM_CHANNELS - 1; + return rf_calib_data->lo[a].fcal; +} + +uint32_t rf_pri_get_vco_idac_cw(uint32_t chanfreq_MHz) { + int32_t a = (int32_t)((chanfreq_MHz-2404)/4 + 0.5); + a = a < 0 ? 0 : a; + if (a > NUM_CHANNELS - 1) + a = NUM_CHANNELS - 1; + return rf_calib_data->lo[a].acal; +} + +void rf_pri_lo_acal(void) { + RF->rfcal_status.acal_status = 0x1; + rf_pri_save_state_for_cal(); + rf_pri_config_mode(E_RF_MODE_LO_ACAL); + + for (int i = 0; i < 21; i++) { + RF->rfcal_ctrlen.acal_en = 1; + RF->vco2.acal_vref_cw = 4; + RF->vco1.lo_vco_idac_cw = 0x10; + RF->vco1.lo_vco_freq_cw = rf_calib_data->lo[i].fcal; + RF->sdm2.lo_sdmin = channel_div_table[i]; + BL602_Delay_US(1); + uint32_t cw = 0x10; + for (int j = 3; j >= 0; j--) { + RF->vco1.lo_vco_idac_cw = cw; + BL602_Delay_US(1); + if (RF->vco2.acal_vco_ud) { + cw -= (1 << j); + } else { + cw += (1 << j); + } + } + RF->vco1.lo_vco_idac_cw = cw; + BL602_Delay_US(1); + if (!RF->vco2.acal_vco_ud) { + if (cw != (1<<5) - 1) { + cw++; + } + } + rf_calib_data->lo[i].acal = cw; + } + rf_pri_restore_state_for_cal(); + RF->rfcal_status.acal_status = 0x3; +} + + +static void rf_pri_rccal_config(uint32_t iq, uint32_t rbb_fc) { + PACK(RF->rbb2, rbb2) + if (iq) { + // i + rbb2.rbb_cap1_fc_i = rbb_fc; + rbb2.rbb_cap2_fc_i = rbb_fc; + } else { + rbb2.rbb_cap1_fc_q = rbb_fc; + rbb2.rbb_cap2_fc_q = rbb_fc; + } +} + + +static void rf_pri_singen_config(uint32_t fcw, uint32_t start_addr_i, uint32_t start_addr_q) { + RF->singen_ctrl0.singen_inc_step0 = fcw; + RF->singen_ctrl2.singen_start_addr0_i = start_addr_i; // 0; + RF->singen_ctrl3.singen_start_addr0_q = start_addr_q; // 0x300; +} + +static void rf_pri_singen_start(void) { + RF->singen_ctrl0.singen_en = 0; + + RF->singen_ctrl0.singen_en = 1; +} + +static void rf_pri_singen_amplitude(uint32_t gain_i, uint32_t gain_q) { + RF->singen_ctrl2.singen_gain_i = gain_i; + RF->singen_ctrl3.singen_gain_q = gain_q; +} + +static uint32_t rf_pri_pm_pwr() { + PACK(RF->dfe_ctrl_6, dfe) { + dfe.rx_pm_freqshift_en = 0; + dfe.rx_pm_en = 0; + } + + PACK(RF->dfe_ctrl_6, dfe) { + dfe.rx_pm_freqshift_en = 1; + dfe.rx_pm_en = 1; + } + + for (; ! RF->dfe_ctrl_6.rx_pm_done; ); + + int32_t pm_iacc = RF->dfe_ctrl_8.value; + pm_iacc = (pm_iacc << 7) >> (7 + 9); + + int32_t pm_qacc = RF->dfe_ctrl_9.value; + pm_qacc = (pm_qacc << 7) >> (7 + 9); + + + PACK(RF->dfe_ctrl_6, dfe) { + dfe.rx_pm_freqshift_en = 0; + dfe.rx_pm_en = 0; + } + + return pm_iacc * pm_iacc + pm_qacc * pm_qacc; +} + + +static uint32_t rf_pri_rccal_iq(uint32_t iq) { + if (iq) { + RF->dfe_ctrl_3.rx_adc_4s_q_en = 0; + RF->dfe_ctrl_3.rx_adc_4s_i_en = 1; + } else { + RF->dfe_ctrl_3.rx_adc_4s_i_en = 0; + RF->dfe_ctrl_3.rx_adc_4s_q_en = 1; + } + + PACK(RF->trx_gain1, trx_gain1) { + trx_gain1.gc_rbb1 = 1; + trx_gain1.gc_rbb2 = 3; + } + + int k1 = 3, k2 = 181; + rf_pri_singen_config(k1, 0, 0x300); + + rf_pri_singen_amplitude(0x3ff, 0x3ff); + + rf_pri_singen_start(); + rf_pri_start_txdfe(); + RF->dfe_ctrl_6.rx_pm_freqshift_cw = k1 << 10; + rf_pri_pm_pwr_avg(iq, 0x400); + + double rccal_power_scale = 0.9 * 0.9; + uint32_t rccal_ref = (uint32_t)(rccal_power_scale * rf_pri_pm_pwr()); + + + PACK(RF->trx_gain1, trx_gain1) { + trx_gain1.gc_rbb1 = 2; + trx_gain1.gc_rbb2 = 6; + } + + rf_pri_singen_config(k2, 0x0, 0x300); + rf_pri_singen_start(); + rf_pri_start_txdfe(); + + RF->dfe_ctrl_6.rx_pm_freqshift_cw = k2 << 10; + + uint32_t rbb_fc = 0; + for (int i = 5; i >= 0; i--) { + rf_pri_rccal_config(iq, rbb_fc + (1 << i)); + uint32_t rccal_val = rf_pri_pm_pwr(); + if (rccal_val > rccal_ref) { + rbb_fc += (1 << i); + } + } + + uint8_t seq_pattern = 0; + for (int i = 0; i < 63; i++) { + rf_pri_rccal_config(iq, rbb_fc); + uint32_t rccal_val = rf_pri_pm_pwr(); + if (rccal_ref < rccal_val) { + seq_pattern = ((seq_pattern << 1) | 1) & 0xf; + rbb_fc++; + } else { + seq_pattern = (seq_pattern << 1) & 0xf; + rbb_fc--; + } + if ((seq_pattern == 0b0101) || (seq_pattern == 0b1010)) + return 3; + } + + return 2; +} + +// resistor-capacitor? +void rf_pri_rccal(void) { + if (RF->rfcal_stateen.rccal_sten) { + RF->rfcal_status.rccal_status = 0; + } else { + RF->rfcal_status.rccal_status = 1; + rf_pri_save_state_for_cal(); + rf_pri_config_mode(E_RF_MODE_RCCAL); + RF->rbb3.rbb_bw = 2; + RF->adda1.dac_rccalsel = 1; + RF->rfcal_ctrlen.rccal_en = 1; + uint32_t i = rf_pri_rccal_iq(1); + uint32_t q = rf_pri_rccal_iq(0); + + __typeof__ (RF->rbb2) data = RF->rbb2; + + rf_calib_data->cal.rbb_cap1_fc_i = data.rbb_cap1_fc_i; + rf_calib_data->cal.rbb_cap1_fc_q = data.rbb_cap1_fc_q; + rf_calib_data->cal.rbb_cap2_fc_i = data.rbb_cap2_fc_i; + rf_calib_data->cal.rbb_cap2_fc_q = data.rbb_cap2_fc_q; + + printf("rbb_cap1_fc_i=%ld,rbb_cap2_fc_i=%ld,rbb_cap1_fc_q=%ld,rbb_cap2_fc_q=%ld\r\n", + (uint32_t)(rf_calib_data->cal.rbb_cap1_fc_i), + (uint32_t)(rf_calib_data->cal.rbb_cap2_fc_i), + (uint32_t)(rf_calib_data->cal.rbb_cap1_fc_q), + (uint32_t)(rf_calib_data->cal.rbb_cap2_fc_q)); + int32_t maxcw = MAX( MAX(rf_calib_data->cal.rbb_cap1_fc_i, rf_calib_data->cal.rbb_cap1_fc_q), + MAX(rf_calib_data->cal.rbb_cap2_fc_i, rf_calib_data->cal.rbb_cap2_fc_q)); + //int32_t tgt_offset_cw = 24; + //int32_t offset_cw = (max_cw + tgt_offset_cw) <= 63 ? tgt_offset_cw : 63 - max_cw; + int32_t offset_cw = 24; + if (maxcw > 39) + offset_cw = 63 - maxcw; + rf_calib_data->cal.rbb_cap1_fc_i += offset_cw; + rf_calib_data->cal.rbb_cap1_fc_q += offset_cw; + rf_calib_data->cal.rbb_cap2_fc_i += offset_cw; + rf_calib_data->cal.rbb_cap2_fc_q += offset_cw; + + rf_pri_rccal_config(1, rf_calib_data->cal.rbb_cap1_fc_i); + rf_pri_rccal_config(0, rf_calib_data->cal.rbb_cap1_fc_q); + + printf("new rbb_cap1_fc_i=%ld,rbb_cap2_fc_i=%ld,rbb_cap1_fc_q=%ld,rbb_cap2_fc_q=%ld\r\n", + (uint32_t)(rf_calib_data->cal.rbb_cap1_fc_i), + (uint32_t)(rf_calib_data->cal.rbb_cap2_fc_i), + (uint32_t)(rf_calib_data->cal.rbb_cap1_fc_q), + (uint32_t)(rf_calib_data->cal.rbb_cap2_fc_q)); + + rf_pri_restore_state_for_cal(); + + if ((i == 2) || (q == 2)) { + RF->rfcal_status.rccal_status = 2; + } else { + RF->rfcal_status.rccal_status = 3; + } + } +} + +static uint32_t txcal_para[E_RF_TXCAL_GAIN_CNT][4]; +static uint32_t txcal_para_a0[E_RF_TXCAL_GAIN_CNT][4] = { + { 0, 2, 6, 256}, + { 0, 2, 1, 256}, + { 0, 2, 0, 304}, + { 0, 4, 0, 240}, + { 0, 4, 0, 304}, + { 0, 4, 0, 352}, + { 0, 4, 0, 416}, + { 0, 4, 0, 416} +}; + +static uint32_t txcal_para_a1[E_RF_TXCAL_GAIN_CNT][4] = { + { 0, 2, 14, 256}, + { 0, 2, 5, 256}, + { 0, 2, 1, 256}, + { 0, 4, 2, 272}, + { 0, 4, 0, 224}, + { 0, 4, 0, 272}, + { 0, 4, 0, 288}, + { 0, 4, 0, 304} +}; + +static void rf_pri_config_txgain(uint32_t gc_tbb_boost, uint32_t gc_tmx, uint32_t gc_tbb) { + PACK(RF->trx_gain1, value) { + value.gc_tbb_boost = gc_tbb_boost; + value.gc_tmx = gc_tmx; + value.gc_tbb = gc_tbb; + } +} + +static int32_t tx_pwr_os = 0; // channel offset +static int32_t tx_pwr_os_temperature = 0; // temperature offset + +static int32_t tx_pwr_table[E_RF_TXPWR_TBL_CNT][7]; +static int32_t tx_pwr_table_origin[E_RF_TXPWR_TBL_CNT][7]; +static int32_t tx_pwr_table_a0[E_RF_TXPWR_TBL_CNT][7] = { + // gain_ctrl_gc_tbb, gain_ctrl_gc_tmx, gain_ctrl_dac_bias_sel, gain_ctrl_gc_tbb_boost + {0, 1, 7, 0x14, 32, 4, 233}, + {0, 1, 7, 0x14, 32, 0, 223}, + {0, 1, 7, 0xe, 32, 4, 212}, + {0, 1, 7, 0xe, 32, 0, 202}, + {0, 1, 7, 0xa, 32, 4 + 1, 188 + 3}, + {0, 1, 7, 0xa, 32, 0 + 1, 178 + 3}, + {0, 1, 7, 8, 32, 4 - 1, 173 - 3}, + {0, 1, 7, 8, 32, 0 - 1, 163 - 3}, + {0, 1, 7, 6, 32, 4 - 1, 153 - 3}, + {0, 1, 7, 6, 32, 0 - 1, 143 - 3}, + {0, 1, 6, 5, 32, 4 + 1, 129 + 3}, + {0, 1, 6, 5, 32, 0 + 1, 119 + 3}, + {0, 1, 6, 4, 32, 4 - 1, 114 - 3}, + {0, 1, 6, 4, 32, 0 - 1, 104 - 3}, + {0, 1, 5, 4, 32, 0, 91}, + {0, 1, 5, 4, 32, -4, 81}, +}; + +static int32_t tx_pwr_table_a1[E_RF_TXPWR_TBL_CNT][7] = { + // gain_ctrl_gc_tbb, gain_ctrl_gc_tmx, gain_ctrl_dac_bias_sel, gain_ctrl_gc_tbb_boost + { 0, 1, 7, 27, 32, -4, 230}, + { 0, 1, 7, 27, 32, -8, 220}, + { 0, 1, 7, 20, 32, -4, 210}, + { 0, 1, 7, 20, 32, -8, 200}, + { 0, 1, 7, 15, 32, -4, 190}, + { 0, 1, 7, 15, 32, -8, 180}, + { 0, 1, 7, 11, 32, -4, 170}, + { 0, 1, 7, 11, 32, -8, 160}, + { 0, 1, 6, 10, 32, -4, 150}, + { 0, 1, 6, 10, 32, -8, 140}, + { 0, 1, 6, 8, 32, -5, 130}, + { 0, 1, 6, 8, 32, -9, 120}, + { 0, 1, 5, 7, 32, -4, 110}, + { 0, 1, 5, 7, 32, -8, 100}, + { 0, 1, 4, 7, 32, -5, 90}, + { 0, 1, 4, 7, 32, -9, 80} +}; + +void rf_pri_query_txgain_table(uint32_t index, uint32_t * rfg_index, uint32_t * dg) { + if (index > 15) index = 15; + *rfg_index = 7 - (index >> 1); + *dg = tx_pwr_table[index][5]; +} + +static int32_t tx_pwr_ch_os[NUM_WIFI_CHANNELS]; // TBD +static int32_t tx_pwr_ch_os_a0[NUM_WIFI_CHANNELS] = { + -16, -13, -10, -8, -5, -2, 0, 2, 5, 7, 9, 11, 14, 18 +}; +static int32_t tx_pwr_ch_os_a1[NUM_WIFI_CHANNELS] = { + // not assigned in the binary, put something here... + // TODO: get some values.. + 13, //2412MHz + 15, //2417MHz + 16, //2422MHz + 18, //2427MHz + 21, //2432MHz + 23, //2437MHz + 0, //2442MHz + 0, //2447MHz + 5, //2452MHz + 7, //2457MHz + 9, //2462MHz + 11, //2467MHz + 14, //2472MHz + 18 //2484MHz +}; + +void rf_pri_update_power_offset(int32_t * power_offset) { + for (int i = 0; i < NUM_WIFI_CHANNELS; i++) { + tx_pwr_ch_os[i] = power_offset[i]; + tx_pwr_ch_os_a1[i] = power_offset[i]; + } +} + +static void rf_pri_set_gain_table_regs() { + // Little-endian? looks okay.. + typedef struct { + uint32_t gain_ctrl_gc_tbb : 5; + uint32_t pad0 : 3; + uint32_t gain_ctrl_gc_tmx : 3; + uint32_t pad1 : 1; + uint32_t gain_ctrl_dac_bias_sel : 2; + uint32_t gain_ctrl_gc_tbb_boost : 2; + } __attribute__((packed)) tbb_gain_t; + union { + tbb_gain_t vals[8]; + uint32_t pack[4]; + } tbb_gain = {.pack = {0}}; + + for (int i = 0, idx = 14; i < 8; i++, idx-=2) { + tbb_gain.vals[i].gain_ctrl_gc_tbb = tx_pwr_table[idx][3]; + tbb_gain.vals[i].gain_ctrl_gc_tmx = tx_pwr_table[idx][2]; + tbb_gain.vals[i].gain_ctrl_dac_bias_sel = tx_pwr_table[idx][1]; + tbb_gain.vals[i].gain_ctrl_gc_tbb_boost = tx_pwr_table[idx][0]; + } + + RF->tbb_gain_index1.value = tbb_gain.pack[0]; + RF->tbb_gain_index2.value = tbb_gain.pack[1]; + RF->tbb_gain_index3.value = tbb_gain.pack[2]; + RF->tbb_gain_index4.value = tbb_gain.pack[3]; +} + +void rf_pri_update_tx_power_offset(uint8_t channel, int8_t * power_offset) { + uint8_t po = power_offset[channel]; + memcpy(tx_pwr_table, tx_pwr_table_origin, sizeof(tx_pwr_table_origin)); + for (int i = 0; i < E_RF_TXPWR_TBL_CNT; i++) { + tx_pwr_table[i][5] = tx_pwr_table[i][5] + po % 4; + tx_pwr_table[i][6] = tx_pwr_table[i][6] + ((int)po / 4) * -10; + } + rf_pri_set_gain_table_regs(); +} + +static uint32_t Tchannels[6] = { + 2412, 2417, 2427, 2442, + 2457, 2472 +}; + +static int32_t Tchannel_os[6] = {2, 3, 3, 4, 6, 8}; +static int32_t Tchannel_os_low[6] = {0, 0, 1, 2, 4, 7}; +static int32_t temps[13] = {-65, -45, -25, -5, 15, 51, + 75, 95, 120, 145, 170, 195, 220}; + +static regs_to_opti opti_regs_data_a0 = { + .vbcore = 10, + .iet = 3, + .vbcore_11n = 10, + .iet_11n = 3, + .vbcore_11g = 10, + .iet_11g = 3, + .vbcore_11b = 10, + .iet_11b = 3, + .lo_fbdv_halfstep_en = 0, + .lo_fbdv_halfstep_en_tx = 0, + .lo_fbdv_halfstep_en_rx = 0, + .clkpll_reset_postdiv = 0, + .clkpll_dither_sel = 0, +}; + +static regs_to_opti opti_regs_data_a1 = { + .vbcore = 0xc, + .iet = 5, + .vbcore_11n = 0xc, + .iet_11n = 5, + .vbcore_11g = 0xc, + .iet_11g = 5, + .vbcore_11b = 0xc, + .iet_11b = 5, + .lo_fbdv_halfstep_en = 1, + .lo_fbdv_halfstep_en_tx = 1, + .lo_fbdv_halfstep_en_rx = 1, + .clkpll_reset_postdiv = 1, + .clkpll_dither_sel = 2, +}; + +regs_to_opti *opti_regs = &opti_regs_data_a1; + +static uint16_t tmxcss[3] = {5,5,5}; + +static int32_t index_os_pre; +static int32_t index_os_pre_mdb; +static int32_t dvga_os_pre; +static int32_t up_dn; + +static void rf_pri_singen_pwrmx_dc(uint32_t amp, uint32_t num_data, int32_t adc_mean_max, int32_t adc_mean_min){ + uint32_t step; + int32_t adc_mean_i = 0; + step = amp >> 1; + while(1) { + rf_pri_singen_amplitude(amp, amp); + rf_pri_singen_start(); + rf_pri_start_txdfe(); + + BL602_Delay_US(10); + adc_mean_i = rf_pri_pm_pwr_avg(1, num_data); + adc_mean_i = adc_mean_i>>10; + printf("amp=%ld,step=%ld,adc_mean_i=%ld\r\n", amp, step, adc_mean_i); + + if(adc_mean_i > adc_mean_max) + amp -= step; + else if (adc_mean_i < adc_mean_min) + amp += step; + else + break; + if(step > 0) + step = step >> 1; + else + break; + } +} + +// TODO: verify me +static void rf_pri_txcal_config(uint32_t param_ind, int32_t val) { + switch (param_ind) { + case E_RF_GAIN: { + PACK(RF->dfe_ctrl_0, dfe) { + dfe.tx_iqc_gain = val; + dfe.tx_iqc_gain_en = 1; + } + break; + } + case E_RF_PHASE: { + val = val >= 0 ? val : (val+0x400); + PACK(RF->dfe_ctrl_0, dfe) { + dfe.tx_iqc_phase = val; + dfe.tx_iqc_phase_en = 1; + } + break; + } + case E_RF_BRANCH_I: { + RF->tbb.tbb_tosdac_i = val; + break; + } + case E_RF_BRANCH_Q: { + RF->tbb.tbb_tosdac_i = val; + break; + } + default: + break; + } +} + +// kinda like Gradient descent to find minimum point? +// todo: verify me +static int32_t rf_pri_txcal_search_core(uint32_t param_ind, uint32_t center, uint32_t delta, uint32_t meas_freq) { + rf_pri_txcal_config(param_ind, center); + BL602_Delay_US(10); + + RF->dfe_ctrl_6.rx_pm_freqshift_cw = meas_freq << 10; + + uint32_t y_center = rf_pri_pm_pwr(); + + int32_t x_center = center; + int32_t x_delta = delta; + + for (int32_t x_left, x_right, y_left, y_right; x_delta; x_delta >>= 1) { + x_left = x_center - x_delta; + x_right = x_center + x_delta; + switch (param_ind) { + case E_RF_BRANCH_I ... E_RF_BRANCH_Q: + x_left = x_left < 0 ? 0 : x_left; + x_right = x_right > 63 ? 63 : x_right; + break; + case E_RF_GAIN: + x_left = x_left < 0 ? 0 : x_left; + x_right = x_right > 2047 ? 2047 : x_right; + break; + case E_RF_PHASE: + x_left = x_left < -512 ? -512 : x_left; + x_right = x_right > 511 ? 511 : x_right; + break; + } + + // left + rf_pri_txcal_config(param_ind, x_left); + BL602_Delay_US(10); + y_left = rf_pri_pm_pwr(); + + if (y_center <= y_left) { + // right + + rf_pri_txcal_config(param_ind, x_right); + BL602_Delay_US(10); + y_right = rf_pri_pm_pwr(); + + if (y_center > y_right) { + x_center = x_right; + y_center = y_right; + } + } else { + x_center = x_left; + y_center = y_left; + } + } + + return x_center; +} + +static void rf_pri_txcal_config_hw() { + typedef struct { + uint32_t tbb_tosdac_i_gc0 : 6; // @ 5 -- 0 # 0xffffffc0 + uint32_t pad0 : 2; + uint32_t tbb_tosdac_q_gc0 : 6; // @ 13 -- 8 # 0xffffc0ff + uint32_t pad1 : 2; + } __attribute__((packed)) tosdac_t; + union { + tosdac_t vals[8]; + uint32_t pack[4]; + } tosdac = {.pack = {0}}; + for (int i = 0; i < 8; i++) { + tosdac.vals[i].tbb_tosdac_i_gc0 = rf_calib_data->txcal[i].tosdac_i; + tosdac.vals[i].tbb_tosdac_q_gc0 = rf_calib_data->txcal[i].tosdac_q; + } + RF->tosdac_ctrl_hw1.value = tosdac.pack[0]; + RF->tosdac_ctrl_hw2.value = tosdac.pack[1]; + RF->tosdac_ctrl_hw3.value = tosdac.pack[2]; + RF->tosdac_ctrl_hw4.value = tosdac.pack[3]; + + __typeof__ (RF->tx_iq_gain_hw0) iq_gain[8]; + + for (int i = 0; i < 8; i++) { + iq_gain[i].tx_iq_gain_comp_gc0 = rf_calib_data->txcal[i].tx_iq_gain_comp; + iq_gain[i].tx_iq_phase_comp_gc0 = rf_calib_data->txcal[i].tx_iq_phase_comp; + } + + RF->tx_iq_gain_hw0.value = iq_gain[0].value; + RF->tx_iq_gain_hw1.value = iq_gain[1].value; + RF->tx_iq_gain_hw2.value = iq_gain[2].value; + RF->tx_iq_gain_hw3.value = iq_gain[3].value; + RF->tx_iq_gain_hw4.value = iq_gain[4].value; + RF->tx_iq_gain_hw5.value = iq_gain[5].value; + RF->tx_iq_gain_hw6.value = iq_gain[6].value; + RF->tx_iq_gain_hw7.value = iq_gain[7].value; +} + +void rf_pri_txcal(void) { + // + PACK(RF->rfcal_status, rfcal_status) { + rfcal_status.lo_leakcal_status = 1; + rfcal_status.tiqcal_status_resv = 1; + } + // + rf_pri_save_state_for_cal(); + rf_pri_config_mode(E_RF_MODE_TXCAL); + rf_pri_config_channel(E_RF_CHANNEL_2424M); // E_RF_CHANNEL_2440M in the leak code + + // + PACK(RF->rfcal_ctrlen, rfcal_ctrlen) { + rfcal_ctrlen.tiqcal_en = 1; + rfcal_ctrlen.lo_leakcal_en = 1; + } + // + RF->rbb3.pwr_det_en = 1; + + RF->pa1.pa_pwrmx_dac_pn_switch = 1; + + RF->tmx.tmx_cs = tmxcss[0]; // leak code use 3 + + uint32_t k1 = 61; + rf_pri_singen_config(k1, 0x0, 0x300); + + for (int i = 0; i < 8; i++) { + // + PACK(RF->pa1, pa1) { + pa1.pa_att_gc = txcal_para[i][0]; + pa1.pa_pwrmx_osdac = txcal_para[i][2]; + } + // + RF->ten_ac.atest_gain_r5 = txcal_para[i][1]; + + // + rf_pri_config_txgain(tx_pwr_table[i<<1][0], 7, tx_pwr_table[i<<1][3]); + // + + BL602_Delay_US(10); + + int32_t adc_mean_min=192; + int32_t adc_mean_max=320; + uint32_t num_data=1024; + rf_pri_singen_pwrmx_dc(txcal_para[i][3],num_data,adc_mean_max,adc_mean_min); + + rf_pri_pm_pwr_avg(1, 0x1000); + + uint32_t tos_i = rf_pri_txcal_search_core(E_RF_BRANCH_I, 32, 16, k1); + rf_pri_txcal_config(E_RF_BRANCH_I, tos_i); + + uint32_t tos_q = rf_pri_txcal_search_core(E_RF_BRANCH_Q, 32, 16, k1); + rf_pri_txcal_config(E_RF_BRANCH_Q, tos_q); + + tos_i = rf_pri_txcal_search_core(E_RF_BRANCH_I, tos_i, 2, k1); + rf_pri_txcal_config(E_RF_BRANCH_I, tos_i); + + uint32_t gain = rf_pri_txcal_search_core(E_RF_GAIN, 0x400, 0x80, 2 * k1); + rf_pri_txcal_config(E_RF_GAIN, gain); + + uint32_t phase = rf_pri_txcal_search_core(E_RF_PHASE, 0, 0x40, 2 * k1); + rf_pri_txcal_config(E_RF_PHASE, phase); + + gain = rf_pri_txcal_search_core(E_RF_GAIN, gain, 0x40, 2 * k1); + rf_pri_txcal_config(E_RF_GAIN, gain); + + phase = rf_pri_txcal_search_core(E_RF_PHASE, 0, 0x20, 2 * k1); + rf_pri_txcal_config(E_RF_PHASE, phase); + + rf_calib_data->txcal[E_RF_TXCAL_GAIN_CNT - 1 - i].tosdac_i = tos_i; + rf_calib_data->txcal[E_RF_TXCAL_GAIN_CNT - 1 - i].tosdac_q = tos_q; + rf_calib_data->txcal[E_RF_TXCAL_GAIN_CNT - 1 - i].tx_iq_gain_comp = gain; + rf_calib_data->txcal[E_RF_TXCAL_GAIN_CNT - 1 - i].tx_iq_phase_comp = phase; + + printf("tosdac_i=%ld,tosdac_q=%ld,tx_iq_gain_comp=%ld,tx_iq_phase_comp=%ld\r\n", + tos_i, tos_q, gain, phase); + } + + rf_pri_txcal_config_hw(); + PACK(RF->rfcal_ctrlen, rfcal_ctrlen) { + rfcal_ctrlen.lo_leakcal_en = 0; + rfcal_ctrlen.tiqcal_en = 0; + } + rf_pri_restore_state_for_cal(); + + PACK(RF->rfcal_status, rfcal_status) { + rfcal_status.lo_leakcal_status = 0x3; + rfcal_status.tiqcal_status_resv = 0x3; + } + + PACK(RF->tbb, tbb) { + tbb.tbb_tosdac_i = rf_calib_data->txcal[3].tosdac_i; + tbb.tbb_tosdac_q = rf_calib_data->txcal[3].tosdac_q; + } + + PACK(RF->dfe_ctrl_0, dfe_ctrl_0) { + dfe_ctrl_0.tx_iqc_gain = rf_calib_data->txcal[3].tx_iq_gain_comp; + dfe_ctrl_0.tx_iqc_phase = rf_calib_data->txcal[3].tx_iq_phase_comp; + } +} + + +void rf_pri_update_param(uint32_t chanfreq_MHz) { + uint32_t low_chan = 7; + int32_t i4 = 8; + + index_os_pre = 0; + index_os_pre_mdb = 0; + dvga_os_pre = 0; + up_dn = 0; + + for (int i = 1; i < 6; i++) { + if (chanfreq_MHz < Tchannels[i]) { + low_chan = i - 1; + break; + } + } + + if (low_chan != 7) { + uint32_t low_chanfreq_Mhz = Tchannels[low_chan]; + int freq_diff = chanfreq_MHz - low_chanfreq_Mhz; + int high_ch = low_chan + 1; + i4 = (uint32_t)((Tchannel_os[high_ch] - Tchannel_os[low_chan]) + * freq_diff) / (Tchannels[high_ch] - low_chanfreq_Mhz) + + Tchannel_os[low_chan]; + + low_chan = (uint32_t)((Tchannel_os_low[high_ch] - Tchannel_os_low[low_chan]) * freq_diff) / + (Tchannels[high_ch] - low_chanfreq_Mhz) + Tchannel_os_low[low_chan]; + } + + int d = 0; + for (int i = 10, j = 4; i != -10; i -=5, j -= 1) { + int i2 = (temps[j] + d) - (20 - low_chan); + d = 0; + if (i2 > i) { + d = i2 - i; + i2 = i; + } + temps[j - 1] = i2; + } + + d = 0; + for (int i = 56, j = 5; i != 91; i += 5, j++) { + int i8 = (temps[j] - d) + (20 - i4); + if (i8 > 95) { + i8 = i8 + (5 - i4 / 4); + } + d = 0; + if (i8 < i) { + d = i - i8; + i8 = i; + } + temps[j + 1] = i8; + } + + temps[4] = 15; + temps[5] = 51; + + // the leak code use tmx_csl/tmx_csh from rf_calib_data + if (chanfreq_MHz < 2438) { + RF->tmx.tmx_cs = tmxcss[1]; + } else { + RF->tmx.tmx_cs = tmxcss[2]; + } + + switch(chanfreq_MHz){ + case 2412: + tx_pwr_os = tx_pwr_ch_os[0]; + break; + case 2417: + tx_pwr_os = tx_pwr_ch_os[1]; + break; + case 2422: + tx_pwr_os = tx_pwr_ch_os[2]; + break; + case 2427: + tx_pwr_os = tx_pwr_ch_os[3]; + break; + case 2432: + tx_pwr_os = tx_pwr_ch_os[4]; + break; + case 2437: + tx_pwr_os = tx_pwr_ch_os[5]; + break; + case 2442: + tx_pwr_os = tx_pwr_ch_os[6]; + break; + case 2447: + tx_pwr_os = tx_pwr_ch_os[7]; + break; + case 2452: + tx_pwr_os = tx_pwr_ch_os[8]; + break; + case 2457: + tx_pwr_os = tx_pwr_ch_os[9]; + break; + case 2462: + tx_pwr_os = tx_pwr_ch_os[10]; + break; + case 2467: + tx_pwr_os = tx_pwr_ch_os[11]; + break; + case 2472: + tx_pwr_os = tx_pwr_ch_os[12]; + break; + case 2484: + tx_pwr_os = tx_pwr_ch_os[13]; + break; + default: + tx_pwr_os = 0; + break; + } + +} + +static int32_t Tthr; + +static int8_t temps_dvga[16] = { + -4, -8, -4, -8, + -4, -8, -4, -8, + -4, -8, -5, -9, + -4, -8, -5, -9, +}; + +void rf_pri_update_dvga_os(int8_t dvga_os) { + for (int i = 0; i < 16; i++) { + temps_dvga[i] = tx_pwr_table[i][5] + dvga_os; + } +} + +// TODO: re-verify this function +void rf_pri_tx_gain_comp(int32_t Tsens) { + + if (((up_dn == 1) && ((Tthr <= Tsens) || (Tsens <= Tthr + -5))) + || ((((up_dn != -1 && up_dn != 1) || (Tsens <= Tthr)) || (Tthr + 5 <= Tsens)))) { + uint32_t dvga_os = 0; + int i; + for (i = 12; i >= 0; i--) { + if (temps[i] <= Tsens) + break; + } + if (i == -1) i = 0; + int32_t index_os = i - 4; + int32_t T = temps[i]; + Tthr = T; + if (Tsens < 35) { + if (T < Tsens) { + Tthr = temps[i + 1]; + if (34 < temps[i + 1]) { + Tthr = T; + } + } else { + index_os = i - 5; + } + } else { + if (T < 36) { + Tthr = temps[i + 1]; + } + } + + if (index_os_pre_mdb < index_os) { + up_dn = 1; + } else { + if (index_os_pre_mdb > index_os) + up_dn = -1; + } + if (index_os < 1) { + dvga_os = 0; + index_os_pre = index_os; + if (index_os != 0) { + dvga_os = -1; + if ((index_os & 1) != 0) { + dvga_os = 1; + } + index_os_pre = (index_os - 1) / 2; + } + } else { + dvga_os = (index_os + 1) & 1; + if (dvga_os == 0) { + dvga_os = -1; + } + index_os_pre = (index_os + 1) / 2; + } + tx_pwr_os_temperature = index_os_pre * -10; + dvga_os_pre = dvga_os; + index_os_pre_mdb = index_os; + } else { + tx_pwr_os_temperature = index_os_pre * -10; + } + + rf_pri_update_dvga_os(dvga_os_pre); + rfc_apply_tx_dvga(temps_dvga); +} + + +void rf_pri_update_txgain_tempos(int16_t tempos) { + tx_pwr_os_temperature = tempos; +} + +int32_t rf_pri_get_txgain_max(void) { + return tx_pwr_table[0][6] + tx_pwr_os + tx_pwr_os_temperature; +} + +int32_t rf_pri_get_txgain_min(void) { + return tx_pwr_table[15][6] + tx_pwr_os + tx_pwr_os_temperature; +} + +uint32_t rf_pri_get_txgain_index(int32_t pwr, uint32_t mode) { + pwr += tx_pwr_os; + if (mode == E_RF_MODE_11B) { + pwr -= 33; + } + for (int i = 0; i < E_RF_TXPWR_TBL_CNT; i++) { + if (pwr >= tx_pwr_table[i][6]) { + return i; + } + } + return E_RF_TXPWR_TBL_CNT - 1; +} + + +static void rf_pri_chipv(uint8_t chipv) { + #define cpy_rev(dest, rev) memcpy(dest, dest##_a##rev, sizeof(dest##_a##rev)); + // init based on chip revision + if (chipv == 0) { + tmxcss[0] = 3; + tmxcss[1] = 6; + tmxcss[2] = 6; + cpy_rev(tx_pwr_table, 0); + memcpy(tx_pwr_table_origin, tx_pwr_table_a0, sizeof(tx_pwr_table_a0)); + cpy_rev(tx_pwr_ch_os, 0); + cpy_rev(txcal_para, 0); + opti_regs = &opti_regs_data_a0; + } + if (chipv == 1) { + tmxcss[0] = 5; + tmxcss[1] = 5; + tmxcss[2] = 5; + cpy_rev(tx_pwr_table, 1); + memcpy(tx_pwr_table_origin, tx_pwr_table_a1, sizeof(tx_pwr_table_a1)); + cpy_rev(tx_pwr_ch_os, 1); + cpy_rev(txcal_para, 1); + opti_regs = &opti_regs_data_a1; + } +} + +static int32_t init_fast = 0; + +static void rf_pri_fixed_val_regs(){ + AON->dcdc18_top_0.dcdc18_vpfm_aon = 3; + HBN->HBN_GLB.sw_ldo11_rt_vout_sel = 8; + PACK(RF->pucr1, pucr1) { + pucr1.pu_sfreg = 1; + pucr1.pu_adda_ldo = 1; + } + AON->xtal_cfg.xtal_capcode_extra_aon = 1; + // leak code also set xtal_capcode_out_aon and xtal_capcode_in_aon + + if (!init_fast) { + BL602_Delay_MS(10); + } + + PACK(RF->pa1, pa1) { + pa1.pa_iaq = 2; + pa1.pa_iet = opti_regs->iet; + pa1.pa_vbcore = opti_regs->vbcore; + pa1.pa_vbcas = 4; + } + PACK(RF->pa_reg_ctrl_hw1, pa_reg_ctrl_hw1) { + pa_reg_ctrl_hw1.pa_iet_11n = opti_regs->iet_11n; + pa_reg_ctrl_hw1.pa_vbcas_11n = 4; + pa_reg_ctrl_hw1.pa_vbcore_11n = opti_regs->vbcore_11n; + } + PACK(RF->pa_reg_ctrl_hw2, pa_reg_ctrl_hw2) { + pa_reg_ctrl_hw2.pa_iet_11g = opti_regs->iet_11g; + pa_reg_ctrl_hw2.pa_vbcore_11g = opti_regs->vbcore_11g; + pa_reg_ctrl_hw2.pa_vbcas_11g = 4; + + pa_reg_ctrl_hw2.pa_iet_11b = opti_regs->iet_11b; + pa_reg_ctrl_hw2.pa_vbcore_11b = opti_regs->vbcore_11b; + pa_reg_ctrl_hw2.pa_vbcas_11b = 4; + } + + RF->adda2.adc_gt_rm = 1; + + RF->fbdv.lo_fbdv_halfstep_en = opti_regs->lo_fbdv_halfstep_en; + + PACK(RF->lo_reg_ctrl_hw1, lo_reg_ctrl_hw1) { + lo_reg_ctrl_hw1.lo_fbdv_halfstep_en_tx = opti_regs->lo_fbdv_halfstep_en_tx; + lo_reg_ctrl_hw1.lo_fbdv_halfstep_en_rx = opti_regs->lo_fbdv_halfstep_en_rx; + // the disassembly uses lo_fbdv_halfstep_en_tx for both, and + // in chipv it also uses lo_fbdv_halfstep_en_tx for both, + // I think it's typo + } + + PACK(RF->lo_reg_ctrl_hw1, lo_reg_ctrl_hw1) { + lo_reg_ctrl_hw1.lo_lf_rz_tx = 0; + lo_reg_ctrl_hw1.lo_lf_cz_tx = 3; + lo_reg_ctrl_hw1.lo_cp_sel_tx = 0; + } + + PACK(RF->pa_reg_wifi_ctrl_hw, pa_reg_wifi_ctrl_hw) { + pa_reg_wifi_ctrl_hw.pa_half_on_wifi = 0; + pa_reg_wifi_ctrl_hw.pa_ib_fix_wifi = 0; + } +} + +static void rf_pri_restore_cal_reg(void) { + PACK(RF->rosdac_ctrl_hw1, rosdac) { + rosdac.rosdac_i_gc0 = rf_calib_data->rxcal[0].rosdac_i; + rosdac.rosdac_q_gc0 = rf_calib_data->rxcal[0].rosdac_q; + rosdac.rosdac_i_gc1 = rf_calib_data->rxcal[1].rosdac_i; + rosdac.rosdac_q_gc1 = rf_calib_data->rxcal[1].rosdac_q; + } + PACK(RF->rosdac_ctrl_hw2, rosdac) { + rosdac.rosdac_i_gc2 = rf_calib_data->rxcal[2].rosdac_i; + rosdac.rosdac_q_gc2 = rf_calib_data->rxcal[2].rosdac_q; + rosdac.rosdac_i_gc3 = rf_calib_data->rxcal[3].rosdac_i; + rosdac.rosdac_q_gc3 = rf_calib_data->rxcal[3].rosdac_q; + } + PACK(RF->rbb2, rbb2) { + rbb2.rbb_cap1_fc_i = rf_calib_data->cal.rbb_cap1_fc_i; + rbb2.rbb_cap1_fc_q = rf_calib_data->cal.rbb_cap1_fc_q; + rbb2.rbb_cap2_fc_i = rf_calib_data->cal.rbb_cap2_fc_i; + rbb2.rbb_cap2_fc_q = rf_calib_data->cal.rbb_cap2_fc_q; + } + + PACK(RF->tbb, tbb) { + tbb.tbb_tosdac_i = rf_calib_data->txcal[3].tosdac_i; + tbb.tbb_tosdac_q = rf_calib_data->txcal[3].tosdac_q; + } + + PACK(RF->dfe_ctrl_0, dfe_ctrl_0) { + dfe_ctrl_0.tx_iqc_gain = rf_calib_data->txcal[3].tx_iq_gain_comp; + dfe_ctrl_0.tx_iqc_phase = rf_calib_data->txcal[3].tx_iq_phase_comp; + } +} + +void rf_pri_init(uint8_t reset, uint8_t chipv) { + rf_pri_chipv(chipv); + init_fast = reset == 0; + + rf_pri_fixed_val_regs(); + + PDS->pu_rst_clkpll.clkpll_reset_postdiv = opti_regs->clkpll_reset_postdiv; + PDS->clkpll_sdm.clkpll_dither_sel = opti_regs->clkpll_dither_sel; + RF->adda1.dac_dvdd_sel = 2; + HBN->HBN_GLB.sw_ldo11soc_vout_sel_aon = 0xc; + + rf_pri_set_gain_table_regs(); + + PDS->clkpll_top_ctrl.clkpll_refclk_sel = 1; + PACK(PDS->clkpll_output_en, clkpll_output_en) { + clkpll_output_en.clkpll_en_480m = 1; + clkpll_output_en.clkpll_en_240m = 1; + clkpll_output_en.clkpll_en_192m = 1; + clkpll_output_en.clkpll_en_160m = 1; + clkpll_output_en.clkpll_en_120m = 1; + clkpll_output_en.clkpll_en_96m = 1; + clkpll_output_en.clkpll_en_80m = 1; + clkpll_output_en.clkpll_en_48m = 1; + } + + if (rf_calib_data->inited && !reset) { + rf_pri_restore_cal_reg(); + } else { + rf_pri_full_cal(); + rf_calib_data->inited = 1; + } +} + +void rf_pri_init_fast(uint32_t flag) { + init_fast = flag; +} + +/// data for different crystal freq +static uint32_t channel_div_table_24M[21] = { + 0x21638e39, 0x2171c71c, 0x21800000, 0x218e38e4, 0x219c71c7, + 0x21aaaaab, 0x21b8e38e, 0x21c71c72, 0x21d55555, 0x21e38e39, + 0x21f1c71c, 0x22000000, 0x220e38e4, 0x221c71c7, 0x222aaaab, + 0x2238e38e, 0x22471c72, 0x22555555, 0x22638e39, 0x2271c71c, + 0x22800000 +}; +static uint16_t channel_cnt_table_24M[21] = { + 0xa6f2, 0xa739, 0xa780, 0xa7c7, 0xa80e, 0xa855, 0xa89c, 0xa8e4, + 0xa92b, 0xa972, 0xa9b9, 0xaa00, 0xaa47, 0xaa8e, 0xaad5, 0xab1c, + 0xab64, 0xabab, 0xabf2, 0xac39, 0xac80 +}; +static uint16_t channel_cnt_range_24M[21] = { + 0xa6a7, 0xa6e7, 0xace7 +}; +static int32_t rx_notch_para_24M[14][2] = { + {0, 0}, {1, 7000000}, {1, 2000000}, {1, -3000000}, {1, -8000000}, {0, 0}, + {1, 6000000}, {1, 1000000}, {1, -4000000}, {1, -9000000}, {0, 0}, {1, 5000000}, + {1, 0}, {0, 0} +}; +static uint16_t fcal_div_24M = 1280; + +static uint32_t channel_div_table_26M[21] = { + 0x1ed20d21, 0x1edf2df3, 0x1eec4ec5, 0x1ef96f97, 0x1f069069, + 0x1f13b13b, 0x1f20d20d, 0x1f2df2df, 0x1f3b13b1, 0x1f483483, + 0x1f555555, 0x1f627627, 0x1f6f96f9, 0x1f7cb7cb, 0x1f89d89e, + 0x1f96f970, 0x1fa41a42, 0x1fb13b14, 0x1fbe5be6, 0x1fcb7cb8, + 0x1fd89d8a +}; +static uint16_t channel_cnt_table_26M[21] = { + 0xa6fc, 0xa743, 0xa78a, 0xa7d1, 0xa819, 0xa860, 0xa8a7, 0xa8ee, + 0xa935, 0xa97c, 0xa9c3, 0xaa0a, 0xaa52, 0xaa99, 0xaae0, 0xab27, + 0xab6e, 0xabb5, 0xabfc, 0xac43, 0xac8b +}; +static uint16_t channel_cnt_range_26M[21] = { + 0xa6b1, 0xa6f1, 0xacf2 +}; +static int32_t rx_notch_para_26M[14][2] = { + {1, 6000000}, {1, 1000000}, {1, -4000000}, {1, -9000000}, {0, 0}, {1, 7000000}, + {1, 2000000}, {1, -3000000}, {1, -8000000}, {0, 0}, {1, 8000000}, {1, 3000000}, + {1, -2000000}, {0, 0} +}; +static uint16_t fcal_div_26M = 1387; + +static uint32_t channel_div_table_32M[21] = { + 0x190aaaab, 0x19155555, 0x19200000, 0x192aaaab, 0x19355555, + 0x19400000, 0x194aaaab, 0x19555555, 0x19600000, 0x196aaaab, + 0x19755555, 0x19800000, 0x198aaaab, 0x19955555, 0x19a00000, + 0x19aaaaab, 0x19b55555, 0x19c00000, 0x19caaaab, 0x19d55555, + 0x19e00000 +}; +static uint16_t channel_cnt_table_32M[21] = { + 0xa6fa, 0xa741, 0xa788, 0xa7d0, 0xa817, 0xa85e, 0xa8a5, 0xa8ec, + 0xa933, 0xa97a, 0xa9c1, 0xaa09, 0xaa50, 0xaa97, 0xaade, 0xab25, + 0xab6c, 0xabb3, 0xabfa, 0xac42, 0xac89 +}; +static uint16_t channel_cnt_range_32M[21] = { + 0xa6af, 0xa6ef, 0xacf0 +}; +static int32_t rx_notch_para_32M[14][2] = { + {0, 0}, {0, 0}, {1, 10000000}, {1, 5000000}, {1, 0}, {1, -5000000}, + {1, -10000000}, {0, 0}, {0, 0}, {1, 7000000}, {1, 2000000}, {1, -3000000}, + {1, -8000000}, {0, 0} +}; +static uint16_t fcal_div_32M = 1707; + +static uint32_t channel_div_table_38M4[21] = { + 0x14de38e4, 0x14e71c72, 0x14f00000, 0x14f8e38e, 0x1501c71c, + 0x150aaaab, 0x15138e39, 0x151c71c7, 0x15255555, 0x152e38e4, + 0x15371c72, 0x15400000, 0x1548e38e, 0x1551c71c, 0x155aaaab, + 0x15638e39, 0x156c71c7, 0x15755555, 0x157e38e4, 0x15871c72, + 0x15900000 +}; +static uint16_t channel_cnt_table_38M4[21] = { + 0xa6f2, 0xa739, 0xa780, 0xa7c7, 0xa80e, 0xa855, 0xa89c, 0xa8e4, + 0xa92b, 0xa972, 0xa9b9, 0xaa00, 0xaa47, 0xaa8e, 0xaad5, 0xab1c, + 0xab64, 0xabab, 0xabf2, 0xac39, 0xac80 +}; +static uint16_t channel_cnt_range_38M4[21] = { + 0xa6a7, 0xa6e7, 0xace7 +}; +static int32_t rx_notch_para_38M4[14][2] = { + {1, 7200000}, {1, 2200000}, {1, -2800000}, {1, -7800000}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {1, 5600000}, {1, 600000}, {1, -4400000}, {1, -9400000}, + {0, 0}, {0, 0} +}; +static uint16_t fcal_div_38M4 = 2048; + +static uint32_t channel_div_table_40M[21] = { + 0x14088889, 0x14111111, 0x1419999a, 0x14222222, 0x142aaaab, + 0x14333333, 0x143bbbbc, 0x14444444, 0x144ccccd, 0x14555555, + 0x145dddde, 0x14666666, 0x146eeeef, 0x14777777, 0x14800000, + 0x14888889, 0x14911111, 0x1499999a, 0x14a22222, 0x14aaaaab, + 0x14b33333 +}; +static uint16_t channel_cnt_table_40M[21] = { + 0xa6eb, 0xa732, 0xa779, 0xa7c0, 0xa808, 0xa84f, + 0xa896, 0xa8dd, 0xa924, 0xa96b, 0xa9b2, 0xa9f9, + 0xaa40, 0xaa87, 0xaacf, 0xab16, 0xab5d, 0xaba4, + 0xabeb, 0xac32, 0xac79 +}; +static uint16_t channel_cnt_range_40M[21] = { + 0xa6a0, 0xa6e0, 0xace0 +}; +static int32_t rx_notch_para_40M[14][2] = { + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 8000000}, {1, 3000000}, + {1, -2000000}, {1, -7000000}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {1, 8000000}, {1, -4000000} +}; +static uint16_t fcal_div_40M = 2133; + +static uint32_t channel_div_table_52M[21] = { + 0xf690690, 0xf6f96f9, 0xf762762, 0xf7cb7cb, 0xf834835, + 0xf89d89e, 0xf906907, 0xf96f970, 0xf9d89d9, 0xfa41a42, + 0xfaaaaab, 0xfb13b14, 0xfb7cb7d, 0xfbe5be6, 0xfc4ec4f, + 0xfcb7cb8, 0xfd20d21, 0xfd89d8a, 0xfdf2df3, 0xfe5be5c, + 0xfec4ec5 +}; +static uint16_t channel_cnt_table_52M[21] = { + 0xa6ed, 0xa734, 0xa77b, 0xa7c2, 0xa809, 0xa850, + 0xa897, 0xa8de, 0xa925, 0xa96d, 0xa9b4, 0xa9fb, + 0xaa42, 0xaa89, 0xaad0, 0xab17, 0xab5e, 0xaba5, + 0xabec, 0xac34, 0xac7b +}; +static uint16_t channel_cnt_range_52M[21] = { + 0xa6a2, 0xa6e2, 0xace2 +}; +static int32_t rx_notch_para_52M[14][2] = { + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 7000000}, + {1, 2000000}, {1, -3000000}, {1, -8000000}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0} +}; +static uint16_t fcal_div_52M = 2773; + +void rf_pri_xtalfreq(uint32_t xtalfreq) { + switch (xtalfreq) { + case E_RF_XTAL_24M: + memcpy(channel_div_table, channel_div_table_24M, sizeof(channel_div_table)); + memcpy(channel_cnt_table, channel_cnt_table_24M, sizeof(channel_cnt_table)); + memcpy(channel_cnt_range, channel_cnt_range_24M, sizeof(channel_cnt_range)); + memcpy(rx_notch_para, rx_notch_para_24M, sizeof(rx_notch_para)); + fcal_div = fcal_div_24M; + break; + case E_RF_XTAL_26M: + memcpy(channel_div_table, channel_div_table_26M, sizeof(channel_div_table)); + memcpy(channel_cnt_table, channel_cnt_table_26M, sizeof(channel_cnt_table)); + memcpy(channel_cnt_range, channel_cnt_range_26M, sizeof(channel_cnt_range)); + memcpy(rx_notch_para, rx_notch_para_26M, sizeof(rx_notch_para)); + fcal_div = fcal_div_26M; + break; + case E_RF_XTAL_32M: + memcpy(channel_div_table, channel_div_table_32M, sizeof(channel_div_table)); + memcpy(channel_cnt_table, channel_cnt_table_32M, sizeof(channel_cnt_table)); + memcpy(channel_cnt_range, channel_cnt_range_32M, sizeof(channel_cnt_range)); + memcpy(rx_notch_para, rx_notch_para_32M, sizeof(rx_notch_para)); + fcal_div = fcal_div_32M; + break; + case E_RF_XTAL_38M4: + default: + memcpy(channel_div_table, channel_div_table_38M4, sizeof(channel_div_table)); + memcpy(channel_cnt_table, channel_cnt_table_38M4, sizeof(channel_cnt_table)); + memcpy(channel_cnt_range, channel_cnt_range_38M4, sizeof(channel_cnt_range)); + memcpy(rx_notch_para, rx_notch_para_38M4, sizeof(rx_notch_para)); + fcal_div = fcal_div_38M4; + break; + case E_RF_XTAL_40M: + memcpy(channel_div_table, channel_div_table_40M, sizeof(channel_div_table)); + memcpy(channel_cnt_table, channel_cnt_table_40M, sizeof(channel_cnt_table)); + memcpy(channel_cnt_range, channel_cnt_range_40M, sizeof(channel_cnt_range)); + memcpy(rx_notch_para, rx_notch_para_40M, sizeof(rx_notch_para)); + fcal_div = fcal_div_40M; + break; + case E_RF_XTAL_52M: + memcpy(channel_div_table, channel_div_table_52M, sizeof(channel_div_table)); + memcpy(channel_cnt_table, channel_cnt_table_52M, sizeof(channel_cnt_table)); + memcpy(channel_cnt_range, channel_cnt_range_52M, sizeof(channel_cnt_range)); + memcpy(rx_notch_para, rx_notch_para_52M, sizeof(rx_notch_para)); + fcal_div = fcal_div_52M; + break; + } +} diff --git a/src/bl602_wifi/driver/phy/phy_rf/macro.h b/src/bl602_wifi/driver/phy/phy_rf/macro.h new file mode 100644 index 0000000..2b706f6 --- /dev/null +++ b/src/bl602_wifi/driver/phy/phy_rf/macro.h @@ -0,0 +1,47 @@ +#ifndef _MACRO_H_ +#define _MACRO_H_ + +#define EXPAND(...) __VA_ARGS__ + +#define EVAL5(...) EXPAND(EXPAND(__VA_ARGS__)) +#define EVAL4(...) EVAL5(EVAL5(__VA_ARGS__)) +#define EVAL3(...) EVAL4(EVAL4(__VA_ARGS__)) +#define EVAL2(...) EVAL3(EVAL3(__VA_ARGS__)) +#define EVAL1(...) EVAL2(EVAL2(__VA_ARGS__)) +#define EVAL(...) EVAL1(EVAL1(__VA_ARGS__)) + +#define FIRST(a, ...) a +#define SECOND(a, b, ...) b + +#define IS_PROBE(...) SECOND(__VA_ARGS__, 0) +#define PROBE() 0,1 +#define NOT_0 PROBE() +#define NOT(x) IS_PROBE(CAT(NOT_, x)) +#define BOOL(x) NOT(NOT(x)) + + +#define EAT(...) +#define DEFER(x) x EMPTY() +#define DEFER2(x) x EMPTY EMPTY()() +#define EMPTY() + +#define CAT(a,b) a ## b + +#define IF(c) _IF(BOOL(c)) +#define _IF(c) CAT(_IF_,c) +#define _IF_0(...) +#define _IF_1(...) __VA_ARGS__ + +#define HAS_ARGS(...) BOOL(FIRST(_END_OF_ARGUMENTS_ __VA_ARGS__)(0)) +#define _END_OF_ARGUMENTS_(...) BOOL(FIRST(__VA_ARGS__)) + +#define APPLY_NEXT(func, a, ...) \ + func(a) \ + IF(HAS_ARGS(__VA_ARGS__)) (DEFER2(_APPLY_NEXT)()(func, __VA_ARGS__)) +#define APPLY(func, ...) \ + IF(HAS_ARGS(__VA_ARGS__)) (EVAL(APPLY_NEXT(func, ##__VA_ARGS__))) +#define _APPLY_NEXT() APPLY_NEXT + +#define PACK(var, name) for (int tip = 1; tip;) for (__typeof__ (var) name = var; tip; tip = 0, var = name) + +#endif \ No newline at end of file diff --git a/src/bl602_wifi/phy_adapt.c b/src/bl602_wifi/driver/phy/phy_rf/phy_adapt.c similarity index 97% rename from src/bl602_wifi/phy_adapt.c rename to src/bl602_wifi/driver/phy/phy_rf/phy_adapt.c index 8235b71..8f8a888 100644 --- a/src/bl602_wifi/phy_adapt.c +++ b/src/bl602_wifi/driver/phy/phy_rf/phy_adapt.c @@ -1,7 +1,7 @@ -#include "phy_adapt.h" -#include "utils.h" -#include "phy_hal.h" -#include "assert.h" +#include +#include +#include +#include static pa_state_t pa_env[4]; // :136:19 @@ -117,7 +117,7 @@ void pa_init(void) { float calc_ppm_dsss(uint8_t rxv_freqoff) { - return ((double)rxv_freqoff) * 0.7; + return ((double)((int8_t)rxv_freqoff)) * 0.7; } float calc_ppm_ofdm(uint16_t rxv_freqoff) { diff --git a/src/bl602_wifi/phy_bl602.c b/src/bl602_wifi/driver/phy/phy_rf/phy_bl602.c similarity index 74% rename from src/bl602_wifi/phy_bl602.c rename to src/bl602_wifi/driver/phy/phy_rf/phy_bl602.c index 4d98ce9..8d4173e 100644 --- a/src/bl602_wifi/phy_bl602.c +++ b/src/bl602_wifi/driver/phy/phy_rf/phy_bl602.c @@ -3,14 +3,17 @@ #include #include #include - -#include "phy_bl602.h" -#include "phy_trpc.h" -#include "rfc_bl602.h" -#include "phy_adapt.h" -#include "phy_tcal.h" -#include "rf.h" -#include "assert.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "macro.h" static int8_t rxgain_offset_vs_temperature; // :79:15 static int8_t poweroffset[14]; // :80:15 @@ -37,13 +40,21 @@ void phy_get_channel(struct phy_channel_info *info, uint8_t index) { } uint8_t phy_get_mac_freq(void) { - return 0x28; + return PHY_BL602_MACCORE_FREQ_MHZ; } uint8_t phy_get_nss(void) { return (uint8_t)(( (int8_t)(MDM->version.nss & 0xf) )- 1); } +uint8_t phy_get_nsts(void) { + return (uint8_t)(( (int8_t)(MDM->version.nsts & 0xf) )- 1); +} + +uint8_t phy_get_ntx(){ + return (uint8_t)(( (int8_t)(MDM->version.ntx & 0xf) )- 1); +} + void phy_get_version(uint32_t *version_1,uint32_t *version_2) { *version_1 = MDM->version.value; *version_2 = 0; @@ -119,18 +130,21 @@ void agc_config(void) { } void bz_phy_reset(void) { + int tx_rampup_time_us = 8; + int tx_rampdn_time_us = 4; // 4 + int tx_padzero_time_us = 0; BZ_PHY->r0x2808.bz_phy_tx_rampup_fm_on = 0x1; - BZ_PHY->r0x2808.bz_phy_tx_rampup_time_us = 0x8; + BZ_PHY->r0x2808.bz_phy_tx_rampup_time_us = tx_rampup_time_us; BZ_PHY->r0x280c.bz_phy_tx_rampdn_fm_on = 0x1; - BZ_PHY->r0x280c.bz_phy_tx_rampdn_time_us = 0x4; - BZ_PHY->r0x280c.bz_phy_tx_rampdn_pad0_time_us = 0x0; + BZ_PHY->r0x280c.bz_phy_tx_rampdn_time_us = tx_rampdn_time_us; + BZ_PHY->r0x280c.bz_phy_tx_rampdn_pad0_time_us = tx_padzero_time_us; BZ_PHY->r0x2854.bz_phy_rx_proc_time_mlsd_us = 0x20; BZ_PHY->r0x2854.bz_phy_rx_proc_time_direct_us = 0x1e; BZ_PHY->r0x2854.bz_phy_rx_proc_time_eq_us = 0xa; BZ_PHY->r0x2854.bz_phy_rx_proc_time_viterbi_us = 0x1e; BZ_PHY->r0x2810.bz_phy_rx_dfe_notch_en = 0x0; BZ_PHY->r0x2810.bz_phy_rx_dfe_toc_en = 0x1; - BZ_PHY->r0x2cac.bz_agc_rbb_ind_min = 0x4; + BZ_PHY_AGC->r0x2cac.bz_agc_rbb_ind_min = 0x4; return ; } @@ -158,7 +172,7 @@ void phy_get_rf_gain_capab(int8_t *max,int8_t *min) { } void phy_get_rf_gain_idx(int8_t *power,uint8_t *idx) { - *idx = (uint8_t)rfc_get_power_level(2, (int)*power * 10); + *idx = (uint8_t)rfc_get_power_level(RFC_FORMATMOD_11N, (int)*power * 10); } void phy_get_rf_gain_idx_vs_mode(uint8_t mode,int8_t *power,uint8_t *idx) { @@ -190,15 +204,22 @@ void phy_hw_set_channel(uint8_t band, uint16_t freq, uint16_t freq1, uint8_t cha MDM->rxchan.rxdsssen = 1; MDM->mdmconf = 0; mdm_reset(); - MDM->txstartdelay = 0xb4; - MDM->txctrl1 = 0x1c13; - MDM->txctrl3 = 0x2d00438; - MDM->TBECTRL0.tbe_count_adjust_20 = 0; - MDM->DCESTIMCTRL.value = 0xf0f; - MDM->DCESTIMCTRL.WAITHTSTF = 7; + + MDM->txstartdelay = 180; + MDM->txctrl1 = 0x1c13; // (txfeofdm80delay = 19, txfeofdm40delay = 28, txfeofdm20delay = 0, txfedsssdelay = 0)(txfeofdm80delay = 0x13, txfeofdm40delay = 0x1c, txfeofdm20delay = 0, txfedsssdelay = 0) + MDM->txctrl3 = 0x2d00438; // mdm_txctrl3_pack(txphyrdyhtdelay = 720, txphyrdynonhtdelay = 1080) + + MDM->TBECTRL0.tbe_count_adjust_20 = 0; // TBE for 60MHz + + MDM->DCESTIMCTRL.value = 0xf0f; // (starthtdc = 0, startdc = 0, delaysynctd20 = 0, delaysync = 0xf, waithtstf = 0xf) + + MDM->DCESTIMCTRL.WAITHTSTF = 7; // For FPGA, divide value by 2 due to timing constraints + MDM->r834.tddchtstfmargin = 0x6; - MDM->SMOOTHCTRL.value = 0x1880c06; + MDM->SMOOTHCTRL.value = 0x1880c06; // smooth enable/auto-selection MDM->tbectrl2 = 0x7f03; + + // No ACI margin in BW=20MHz due to latency on HTSIG decoding AGC->riu_rwnxagcaci20marg0 = 0; AGC->riu_rwnxagcaci20marg1 = 0; AGC->riu_rwnxagcaci20marg2 = 0; @@ -209,7 +230,7 @@ void phy_hw_set_channel(uint8_t band, uint16_t freq, uint16_t freq1, uint8_t cha AGC->riu_iqestiterclr = 1; } - rf_set_channel(chantype,freq1); + rf_set_channel(chantype, freq1); uint8_t channel = 0; @@ -231,19 +252,54 @@ void phy_set_channel(uint8_t band,uint8_t type,uint16_t prim20_freq,uint16_t cen extern uint32_t agcmem[]; -void phy_init(phy_cfg_tag *config) { - MDM->mdmconf = 0; +static void agc_download() { + AGC->RWNXAGCCNTL.agcfsmreset = 1; + + MDM->r0x874.mdm_agcmemclkforce = 1; + + for (int i = 0; i < PHY_BL602_AGC_MEM_SIZE / 4; i++) + AGCRAM->agcram[i] = agcmem[i]; + + MDM->r0x874.mdm_agcmemclkforce = 0; + AGC->RWNXAGCCNTL.agcfsmreset = 0; + AGC->r0xc020.rc_paoff_delay = 0x14; +} + +static void phy_hw_init(const struct phy_bl602_cfg_tag *cfg) { + MDM->mdmconf = BW_20MHZ; mdm_reset(); + + // realname = rxmode MDM->rxchan.value = 0x20d; + /* + PACK(MDM->rxchan, rxmode) { + rxmode.rxdsssen = 1; // MDM_RXDSSSEN_BIT + rxmode.pad0 = 0b11; // bit 2-3 MDM_RXMMEN_BIT MDM_RXGFEN_BIT + rxmode.pad2 = 1; // bit 9 MDM_RXSTBCEN_BIT + } + */ MDM->rxchan.rxnssmax = phy_get_nss(); - MDM->rxchan.rxndpnstsmax = MDM->version.nsts; + MDM->rxchan.rxndpnstsmax = phy_get_nsts(); MDM->rxchan.rxldpcen = MDM->version.ldpcdec; MDM->rxchan.rxvhten = phy_vht_supported(); MDM->rxchan.rxmumimoen = MDM->version.mu_mimo_rx; - MDM->r3024.precomp = 0x2D; + MDM->r3024.precomp = 45; + + // Rx frame violation check + // [31:15]: VHT + // [14: 4]: HT + // [ 3: 0]: NON-HT MDM->rxframeviolationmask = 0xffffffff; MDM->txchan.value = 0x20d; + /* + PACK(MDM->txchan, txmode) { + txmode.txdsssen = 1; // MDM_TXDSSSEN_BIT + txmode.pad1 = 0b11; // bit 2-3 MDM_TXMMEN_BIT MDM_TXGFEN_BIT + txmode.pad3 = 1; // bit 9 MDM_TXSTBCEN_BIT + } + */ + MDM->txchan.txnssmax = phy_get_nss(); MDM->txchan.ntxmax = phy_get_ntx(); MDM->txchan.txcbwmax = MDM->version.chbw; @@ -251,10 +307,16 @@ void phy_init(phy_cfg_tag *config) { MDM->txchan.vht = phy_vht_supported(); MDM->txchan.txmumimoen = MDM->version.mu_mimo_tx; + // AGC reset mode + // Don't turn off RF if rxreq de-asserted for few cycles after a RXERR MDM->r834.rxtdctrl1 = 1; + + // Enable automatic smoothing filter selection from SNR, then disable force MDM->SMOOTHCTRL.CFGSMOOTHFORCE = 0; MDM->SMOOTHSNRTHR.smoothsnrthrhigh = 0x1b; MDM->SMOOTHSNRTHR.smoothsnrthrmid = 0xf; + + // limit NDBPSMAX to 1x1 80 MCS7 LGI(292.5Mb/s) / SGI (325.0Mb/s) MDM->rxctrl1 = 0x4920492; MDM->r0x874.rcclkforce = 1; @@ -266,27 +328,33 @@ void phy_init(phy_cfg_tag *config) { AGC->r0xb110.riu_rxiqgaincompen = 0; AGC->riu_iqestiterclr = 0; } + + // limit RIU to 1 or 2 antenna active depending on modem capabilities AGC->activeant = 1; + + // limit AGC with a single antenna (path0) AGC->RWNXAGCCNTL.combpathsel = 1; + + // CCA timeout AGC->RWNXAGCCCATIMEOUT = 4000000; AGC->irqmacccatimeouten.irqmacccatimeouten = 1; + agc_config(); - AGC->RWNXAGCCNTL.agcfsmreset = 1; - MDM->r0x874.mdm_agcmemclkforce = 1; + agc_download(); +} + +void phy_init(phy_cfg_tag *config) { + const struct phy_bl602_cfg_tag *cfg = (const struct phy_bl602_cfg_tag *)&config->parameters; + phy_hw_init(cfg); - for (int i = 0; i < 0x200; i++) - AGCRAM->agcram[i] = agcmem[i]; - - MDM->r0x874.mdm_agcmemclkforce = 0; - AGC->RWNXAGCCNTL.agcfsmreset = 0; - AGC->r0xc020.rc_paoff_delay = 0x14; phy_env[0].cfg.reserved = (config->parameters)[0]; - phy_env[0].chnl_center1_freq = 0xff; - phy_env[0].chnl_center2_freq = 0xff; - phy_env[0].chnl_prim20_freq = 0xff; - phy_env[0].band = 0x00; + phy_env[0].chnl_center1_freq = PHY_UNUSED; + phy_env[0].chnl_center2_freq = PHY_UNUSED; + phy_env[0].chnl_prim20_freq = PHY_UNUSED; + phy_env[0].band = PHY_BAND_2G4; phy_env[0].chnl_type = PHY_CHNL_BW_OTHER; + trpc_init(); pa_init(); phy_tcal_reset(); @@ -294,9 +362,9 @@ void phy_init(phy_cfg_tag *config) { } uint8_t phy_vht_supported() { - if (MDM->version.vht) // TODO: verify this cond + if (MDM->version.vht) return 1; - return ((MDM->version.chbw) >> 1) & 1; + return MDM->version.chbw > PHY_CHNL_BW_40; } uint8_t phy_ldpc_rx_supported(void) { @@ -322,7 +390,8 @@ uint8_t phy_mu_mimo_tx_supported(void) { void phy_rc_isr(void) { uint32_t val = AGC->rwnxmacintstatmasked.value; AGC->rwnxmacintack = val; - if (val & 0x100) { + if (val & 0x100) { + // RIU_IRQMACCCATIMEOUTMASKED_BIT mdm_reset(); } } diff --git a/src/bl602_wifi/phy_hal.c b/src/bl602_wifi/driver/phy/phy_rf/phy_hal.c similarity index 97% rename from src/bl602_wifi/phy_hal.c rename to src/bl602_wifi/driver/phy/phy_rf/phy_hal.c index 3d44b30..2875832 100644 --- a/src/bl602_wifi/phy_hal.c +++ b/src/bl602_wifi/driver/phy/phy_rf/phy_hal.c @@ -1,4 +1,4 @@ -#include "phy_hal.h" +#include #include static struct phy_hal_tag hal_env; diff --git a/src/bl602_wifi/phy_helper.c b/src/bl602_wifi/driver/phy/phy_rf/phy_helper.c similarity index 99% rename from src/bl602_wifi/phy_helper.c rename to src/bl602_wifi/driver/phy/phy_rf/phy_helper.c index 45a5c1f..e342402 100644 --- a/src/bl602_wifi/phy_helper.c +++ b/src/bl602_wifi/driver/phy/phy_rf/phy_helper.c @@ -1,4 +1,4 @@ -#include "phy_helper.h" +#include #include #include #include diff --git a/src/bl602_wifi/phy_tcal.c b/src/bl602_wifi/driver/phy/phy_rf/phy_tcal.c similarity index 87% rename from src/bl602_wifi/phy_tcal.c rename to src/bl602_wifi/driver/phy/phy_rf/phy_tcal.c index 5d625b8..c2cdded 100644 --- a/src/bl602_wifi/phy_tcal.c +++ b/src/bl602_wifi/driver/phy/phy_rf/phy_tcal.c @@ -1,14 +1,14 @@ -#include "phy_tcal.h" -#include "phy_hal.h" -#include "phy_bl602.h" -#include "phy_trpc.h" -#include "bl602_rf_private.h" -#include "utils.h" +#include +#include +#include +#include +#include +#include static struct tcal_tag tcal_env; // :41:24 void phy_tcal_reset(void) { - memset(&tcal_env,0,0x38); + memset(&tcal_env, 0, sizeof(tcal_env)); tcal_env.prev_temperature = 0x19; tcal_env.last_action_temperature[0] = 0x19; tcal_env.last_action_temperature[1] = 0x19; diff --git a/src/bl602_wifi/phy_trpc.c b/src/bl602_wifi/driver/phy/phy_rf/phy_trpc.c similarity index 96% rename from src/bl602_wifi/phy_trpc.c rename to src/bl602_wifi/driver/phy/phy_rf/phy_trpc.c index ac39fe9..1e758d6 100644 --- a/src/bl602_wifi/phy_trpc.c +++ b/src/bl602_wifi/driver/phy/phy_rf/phy_trpc.c @@ -1,7 +1,7 @@ -#include "phy_trpc.h" -#include "phy_bl602.h" -#include "bl602_rf_private.h" -#include "utils.h" +#include +#include +#include +#include static int8_t txpwr_vs_rate_table[3][8] = { {0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12}, diff --git a/src/bl602_wifi/rf.c b/src/bl602_wifi/driver/phy/phy_rf/rf.c similarity index 52% rename from src/bl602_wifi/rf.c rename to src/bl602_wifi/driver/phy/phy_rf/rf.c index 8c6b786..cc2d079 100644 --- a/src/bl602_wifi/rf.c +++ b/src/bl602_wifi/driver/phy/phy_rf/rf.c @@ -1,5 +1,5 @@ -#include "rf.h" -#include "rfc_bl602.h" +#include +#include void rf_set_channel(uint8_t bandwidth, uint16_t channel_freq) { rfc_config_channel(channel_freq); @@ -10,12 +10,8 @@ void rf_clkpll_isr(void) { } void rf_init(void) { - __asm( - "csrrci a5, mstatus, 0x8\n\t" - "andi a5, a5, 0x8\n\t" - "beqz a5, .L0\n\t" - "csrrsi zero, mstatus, 0x8\n\t" - ".L0:" + __asm("csrci mstatus, 8\n\t" + "csrsi mstatus, 8\n\t" ); } diff --git a/src/bl602_wifi/driver/phy/phy_rf/rf_private_save.h b/src/bl602_wifi/driver/phy/phy_rf/rf_private_save.h new file mode 100644 index 0000000..06aa13b --- /dev/null +++ b/src/bl602_wifi/driver/phy/phy_rf/rf_private_save.h @@ -0,0 +1,29 @@ +#ifdef RF_PRI_SAVE +RF_PRI_SAVE(rf_fsm_ctrl_hw); +RF_PRI_SAVE(rfctrl_hw_en); +RF_PRI_SAVE(rfcal_ctrlen); +RF_PRI_SAVE(pucr1); +RF_PRI_SAVE(fbdv); +RF_PRI_SAVE(sdm1); +RF_PRI_SAVE(sdm2); +RF_PRI_SAVE(rbb3); +RF_PRI_SAVE(adda1); +RF_PRI_SAVE(dfe_ctrl_0); +RF_PRI_SAVE(dfe_ctrl_3); +RF_PRI_SAVE(dfe_ctrl_6); +RF_PRI_SAVE(dfe_ctrl_7); +RF_PRI_SAVE(trx_gain1); +RF_PRI_SAVE(singen_ctrl0); +RF_PRI_SAVE(singen_ctrl2); +RF_PRI_SAVE(singen_ctrl3); +RF_PRI_SAVE(rf_sram_ctrl0); +RF_PRI_SAVE(rf_sram_ctrl1); +RF_PRI_SAVE(rf_sram_ctrl2); +RF_PRI_SAVE(rf_resv_reg_1); +RF_PRI_SAVE(pa1); +RF_PRI_SAVE(ten_ac); +RF_PRI_SAVE(rfif_dfe_ctrl0); +RF_PRI_SAVE(tbb); +RF_PRI_SAVE(vco2); +#undef RF_PRI_SAVE +#endif \ No newline at end of file diff --git a/src/bl602_wifi/driver/phy/phy_rf/rfc_bl602.c b/src/bl602_wifi/driver/phy/phy_rf/rfc_bl602.c new file mode 100644 index 0000000..c3374ed --- /dev/null +++ b/src/bl602_wifi/driver/phy/phy_rf/rfc_bl602.c @@ -0,0 +1,784 @@ + +#include +#include +#include + +#include +#include +#include +#include + +#define prefix "[RFC] " + +static int inited = 0; +static double xtalfreq_MHz = 40.0; +static void wait_us(uint32_t); +static void wait_ms(uint32_t); +static void _set_rfc(); +static void _set_mdm(); +static void _set_rf_channel_sw(uint32_t); +static void _set_rf_channel_hw(uint32_t); +static uint32_t _calc_sdm_cw(float xtalfreq_MHz, float freq); +//static void _calc_sdm_params(uint32_t xtalfreq,uint32_t *lo_center_freq_mhz,uint32_t *lo_sdmin_center,uint32_t *lo_sdmin_1m,uint32_t *lo_sdmin_if); +static void _set_rfc_powercontrol(uint32_t pc_mode); + +// todo: check me +static void _sync_tx_power_offset() { + uint32_t rfg_index; + uint32_t dg; + + typedef struct { + uint32_t rf_tbb_ind_gc : 3; // @ 2 -- 0 # 0xfffffff8 + uint32_t pad0 : 1; + } __attribute__((packed)) rf_tbb_ind_t; + union { + rf_tbb_ind_t val[16]; + uint32_t pack[2]; + } rf_tbb_ind = {.pack = {0}}; + typedef struct { + uint32_t tx_dvga_gain_qdb_gc : 7; // @ 6 -- 0 # 0xffffff80 + uint32_t pad0 : 1; + } __attribute__((packed)) dvga_gain_t; + union { + dvga_gain_t val[16]; + uint32_t pack[4]; + } dvga_gain = {.pack = {0}}; + for (int i = 0; i < 16; i++) { + rf_pri_query_txgain_table(i, &rfg_index, &dg); + rf_tbb_ind.val[i].rf_tbb_ind_gc = rfg_index & 7; + dvga_gain.val[i].tx_dvga_gain_qdb_gc = dg; + } + RF->dfe_ctrl_16.value = rf_tbb_ind.pack[0]; + RF->dfe_ctrl_12.value = dvga_gain.pack[0]; + RF->dfe_ctrl_13.value = dvga_gain.pack[1]; + RF->dfe_ctrl_17.value = rf_tbb_ind.pack[1]; + RF->dfe_ctrl_14.value = dvga_gain.pack[2]; + RF->dfe_ctrl_15.value = dvga_gain.pack[3]; +} + +void rfc_apply_tx_power_offset(uint8_t channel, int8_t *power_offset) { + rf_pri_update_tx_power_offset(channel, power_offset); + _sync_tx_power_offset(); +} + +// todo: check me +void rfc_apply_tx_dvga(int8_t *dvga_qdb) { + uint32_t dvga_qdb_align[4]; + memcpy(dvga_qdb_align, dvga_qdb, sizeof(dvga_qdb_align)); + dvga_qdb_align[0] &= 0x7f7f7f7f; + dvga_qdb_align[1] &= 0x7f7f7f7f; + dvga_qdb_align[2] &= 0x7f7f7f7f; + dvga_qdb_align[3] &= 0x7f7f7f7f; + RF->dfe_ctrl_12.value = dvga_qdb_align[0]; + RF->dfe_ctrl_13.value = dvga_qdb_align[1]; + RF->dfe_ctrl_14.value = dvga_qdb_align[2]; + RF->dfe_ctrl_15.value = dvga_qdb_align[3]; +} + +// todo: verify me +void rfc_apply_tx_dvga_offset(int8_t offset_qdb) { + volatile uint8_t * gain = (volatile uint8_t *) (&RF->dfe_ctrl_12); + for (int i = 0; i < 16; i++) { + uint8_t vold_gain = gain[i]; + int old_gain = ((int)vold_gain << 0x19) >> 0x19; + int new_gain = RF->dfe_ctrl_12.tx_dvga_gain_qdb_gc0 + offset_qdb; + if (new_gain > 24) + new_gain = 24; + if (new_gain < -48) + new_gain = -48; + gain[i] = (vold_gain & 0x80) | (new_gain & 0x7f); + } +} + +void rfc_rxdfe_set_notch0(uint8_t en, uint8_t alpha, int8_t nrmfc) { + RF->r0x1700.rf_rx_notch0_en = en; + RF->r0x1700.rf_rx_notch0_alpha = alpha; + RF->r0x1700.rf_rx_notch0_nrmfc = nrmfc; +} + +static void _set_rf_channel_hw(uint32_t channel_freq) { + RF->rf_fsm_ctrl0.rf_ch_ind_wifi = channel_freq & 0xfff; + RF->rf_fsm_ctrl1.rf_fsm_lo_rdy_rst = 1; + wait_us(10); + RF->rf_fsm_ctrl1.rf_fsm_lo_rdy_rst = 0; + wait_us(10); + RF->rf_fsm_ctrl_hw.rf_fsm_ctrl_en = 0; + wait_us(10); + RF->rf_fsm_ctrl_hw.rf_fsm_ctrl_en = 1; + wait_us(10); + RF->rf_fsm_ctrl2.rf_fsm_st_dbg = 1; + wait_us(10); + RF->rf_fsm_ctrl2.rf_fsm_st_dbg_en = 1; + wait_us(10); + RF->rf_fsm_ctrl2.rf_fsm_st_dbg = 2; + wait_us(100); + RF->rf_fsm_ctrl2.rf_fsm_st_dbg_en = 0; + wait_us(10); +} + +static void _print_channel_info() { + printf("Channel information:\r\n"); + printf(" lo_sdmin_hw %lx\r\n", RF->sdm3.lo_sdmin_hw); + printf(" lo_sdmbypass_hw %ld\r\n", RF->sdm1.lo_sdm_bypass_hw); + printf(" lo_vco_idac_cw_hw %lx\r\n", RF->vco1.lo_vco_idac_cw_hw); + printf(" lo_vco_freq_cw_hw %lx\r\n", RF->vco1.lo_vco_freq_cw_hw); + printf(" lo_unlocked %ld\r\n", RF->rf_fsm_ctrl_sw.lo_unlocked); + printf(" lo_halfstep_en_hw %ld\r\n", RF->fbdv.lo_fbdv_halfstep_en_hw); + printf(" lo_slipped_up"); + for (int i = 0; i < 8; i++) { + wait_us(1000); + printf("%ld", RF->lo.lo_slipped_up ? (uint32_t)1 : (uint32_t)0); + } + printf("\r\n"); + printf(" lo_slipped_dn "); + for (int i = 0; i < 8; i++) { + wait_us(1000); + printf("%ld", RF->lo.lo_slipped_dn ? (uint32_t)1 : (uint32_t)0); + } + printf("\r\n"); +} + +void rfc_config_channel(uint32_t channel_freq) { + RF->rfif_dig_ctrl.rfif_int_lo_unlocked_mask = 1; + RF->rfctrl_hw_en.lo_ctrl_hw = 1; + RF->rfctrl_hw_en.sdm_ctrl_hw = 1; + RF->rfctrl_hw_en.pu_ctrl_hw = 1; + + _set_rf_channel_hw(channel_freq); + _print_channel_info(); + rf_pri_update_param(channel_freq); + uint8_t ncf_on; + int32_t ncf_freq_Hz; + rf_pri_get_notch_param(channel_freq, &ncf_on, (int32_t *)&ncf_freq_Hz); + double freq = ncf_freq_Hz; + freq /= 40000000.0; + freq *= 256.0; + freq += 0.5; + int32_t new_freq = freq; + rfc_rxdfe_set_notch0(ncf_on, 1, new_freq); + RF->rfif_dig_ctrl.rfif_int_lo_unlocked_mask = 0; +} + +void rfc_config_channel_sw(uint32_t channel_freq) { + RF->rfctrl_hw_en.lo_ctrl_hw = 0; + RF->rfctrl_hw_en.sdm_ctrl_hw = 0; + RF->rfctrl_hw_en.pu_ctrl_hw = 0; + _set_rf_channel_sw(channel_freq); + + rf_pri_update_param(channel_freq); + uint8_t ncf_on; + int32_t ncf_freq_Hz; + rf_pri_get_notch_param(channel_freq, &ncf_on, &ncf_freq_Hz); + double ncf_fs_Hz = 40 * 1000 * 1000; + int8_t ncf_nrmfc = (int8_t)((ncf_freq_Hz / ncf_fs_Hz) * (1 << 8) + 0.5); + uint8_t ncf_alpha = 1; + rfc_rxdfe_set_notch0(ncf_on, ncf_alpha, ncf_nrmfc); +} + + +void rfc_config_power(uint32_t mode, uint32_t tbb_boost, uint32_t tbb, uint32_t tmx) { + _set_rfc_powercontrol(mode); + + RF->trx_gain1.gc_tbb_boost = tbb_boost; + RF->trx_gain1.gc_tbb = tbb; + RF->trx_gain1.gc_tmx = tmx; +} + + +void rfc_config_bandwidth(uint32_t mode) { + if (mode == RFC_BW_20M) { + // dac + PDS->clkpll_output_en.clkpll_en_div2_480m = 0; + + // adc + RF->adda2.adc_clk_div_sel = 1; + RF->rfif_dig_ctrl.rfckg_rxclk_div2_mode = 0; + + // rbb bw + RF->rbb3.rbb_bw = 2; + // rmxgm + RF->rmxgm.rmxgm_10m_mode_en = 0; + } + else if (mode == RFC_BW_10M) { + // dac + PDS->clkpll_output_en.clkpll_en_div2_480m = 1; + + // adc + + RF->adda2.adc_clk_div_sel = 0; + RF->rfif_dig_ctrl.rfckg_rxclk_div2_mode = 1; + + // rbb bw + RF->rbb3.rbb_bw = 1; + + // rmxgm + RF->rmxgm.rmxgm_10m_mode_en = 1; + } +} + + +uint32_t rfc_get_power_level(uint32_t formatmod, int32_t power) { + if (formatmod > 2) + formatmod = 0; + return rf_pri_get_txgain_index(power, formatmod) << 2; +} + +void rfc_init(uint32_t xtalfreq_hz) { + RF->rfif_dfe_ctrl0.bbmode_4s = 0; + RF->rfif_dfe_ctrl0.bbmode_4s_en = 1; + int xtal_mode = 4; + switch (xtalfreq_hz) { + case 24000000: + xtal_mode = 1; + break; + case 32000000: + xtal_mode = 2; + break; + case 38400000: + xtal_mode = 3; + break; + case 52000000: + xtal_mode = 5; + break; + case 40000000: + default: + break; + } + rf_pri_xtalfreq(xtal_mode); + rf_pri_init(!inited, 1); + inited = 1; + + + _set_rfc(xtalfreq_hz); + _set_mdm(); + + RF->rfif_dfe_ctrl0.bbmode_4s_en = 0; + + // leak code has RF Optimized and CFG_RF_ICAL here + RF->rf_fsm_ctrl_hw.rf_fsm_t2r_cal_mode = 0; + + PDS->clkpll_output_en.clkpll_en_80m = 0; + wait_us(1); + RF->rf_fsm_ctrl_hw.rf_fsm_t2r_cal_mode = 1; + wait_us(1); + PDS->clkpll_output_en.clkpll_en_80m = 1; + + // _check_config(); skipped + printf("rf controller init done\r\n"); +} + +void rfc_reset() { + inited = 0; + rfc_init(xtalfreq_MHz * 1000 * 1000); +} + +static uint32_t _calc_sdm_cw(float xtalfreq_MHz, float freq) { + return (((freq * 4.0) / 3.0) / xtalfreq_MHz) * (1<<22); +} + +void rfc_ver_set(uint8_t ver) { + return ; +} + +void rfc_wlan_mode_force(uint32_t force_mode) { + if (force_mode < 3) { + RF->rfif_dfe_ctrl0.wifimode_4s = force_mode; + RF->rfif_dfe_ctrl0.wifimode_4s_en = 1; + } else { + RF->rfif_dfe_ctrl0.wifimode_4s = 0; + RF->rfif_dfe_ctrl0.wifimode_4s_en = 0; + } +} + +void rfc_txdfe_start() { + RF->rfif_dfe_ctrl0.tx_dfe_en_4s = 1; + wait_us(1); + RF->rfif_dfe_ctrl0.tx_dfe_en_4s_en = 1; +} + +void rfc_txdfe_stop() { + RF->rfif_dfe_ctrl0.tx_dfe_en_4s = 0; + wait_us(1); + RF->rfif_dfe_ctrl0.tx_dfe_en_4s_en = 0; +} + +void rfc_txdfe_mux(int8_t signal_source) { + RF->rfif_dfe_ctrl0.tx_test_sel = signal_source & 3; +} + +void rfc_txdfe_set_dvga(int8_t dvga_qdb) { + if (dvga_qdb < -48 || dvga_qdb > +24) { + printf(prefix "dvga_qdb out of range -48~+24,skip\r\n"); + return ; + } + RF->dfe_ctrl_0.tx_dvga_gain_qdb = dvga_qdb; +} + +void rfc_txdfe_set_iqgaincomp(uint8_t en,uint16_t coeff) { + RF->dfe_ctrl_0.tx_iqc_gain_en = en; + RF->dfe_ctrl_0.tx_iqc_gain = coeff; +} + +void rfc_txdfe_set_iqphasecomp(uint8_t en,int16_t coeff) { + RF->dfe_ctrl_0.tx_iqc_phase_en = en; + RF->dfe_ctrl_0.tx_iqc_phase = coeff; +} + +void rfc_txdfe_set_dccomp(int16_t dcc_i,int16_t dcc_q) { + RF->dfe_ctrl_1.tx_dac_os_i = dcc_i; + RF->dfe_ctrl_1.tx_dac_os_q = dcc_q; + +} + +void rfc_txdfe_set_iqswap(uint8_t swap_on) { + RF->dfe_ctrl_1.tx_dac_iq_swap = swap_on; +} + +void rfc_rxdfe_start() {} +void rfc_rxdfe_stop(); +void rfc_rxdfe_set_iqgaincomp(uint8_t en,uint16_t coeff); +void rfc_rxdfe_set_iqphasecomp(uint8_t en,int16_t coeff); +void rfc_rxdfe_set_dccomp(int16_t dcc_i,int16_t dcc_q); +void rfc_rxdfe_set_iqswap(uint8_t swap_on); +void rfc_rxdfe_set_notch0(uint8_t en,uint8_t alpha,int8_t nrmfc); +void rfc_rxdfe_set_notch1(uint8_t en,uint8_t alpha,int8_t nrmfc); + + +void rfc_sg_start(uint32_t inc_step,uint32_t gain_i,uint32_t gain_q,uint32_t addr_i,uint32_t addr_q) { + RF->singen_ctrl0.singen_en = 0; + RF->singen_ctrl0.singen_inc_step0 = inc_step; + RF->singen_ctrl0.singen_clkdiv_n = 0; // work clock + RF->singen_ctrl1.singen_mode_i = RFC_SG_SINGLE_TONE; // 0: single tone, 1: two tone, 2: ramp + RF->singen_ctrl1.singen_mode_q = RFC_SG_SINGLE_TONE; // 0: single tone, 1: two tone, 2: ramp + + RF->singen_ctrl2.singen_gain_i = gain_i; + RF->singen_ctrl3.singen_gain_q = gain_q; + + RF->singen_ctrl2.singen_start_addr0_i = addr_i; + RF->singen_ctrl3.singen_start_addr0_q = addr_q; + + RF->singen_ctrl0.singen_en = 1; +} + +void rfc_sg_stop() { + RF->singen_ctrl0.singen_en = 0; +} + +uint32_t rfc_pm_start(uint32_t insel,int32_t freq_cw,uint32_t acclen,uint32_t rshiftlen, + int32_t *raw_acc_i,int32_t *raw_acc_q) { + + // turn off and configure power meter + RF->dfe_ctrl_6.rx_pm_en = 0; + + RF->dfe_ctrl_7.rx_pm_start_ofs = 1024; + + RF->dfe_ctrl_7.rx_pm_acc_len = acclen; + RF->dfe_ctrl_6.rx_pm_freqshift_en = (freq_cw != 0); + RF->dfe_ctrl_6.rx_pm_freqshift_cw = freq_cw; + + RF->dfe_ctrl_6.rx_pm_in_sel = insel; + RF->dfe_ctrl_6.rx_pm_en = 1; + + wait_us(100); + + int32_t iqacc_i = RF->dfe_ctrl_8.rx_pm_iqacc_i; // 25BIT + int32_t iqacc_q = RF->dfe_ctrl_9.rx_pm_iqacc_q; // 25BIT + iqacc_i = iqacc_i << 7 >> 7; + iqacc_q = iqacc_q << 7 >> 7; + + if (raw_acc_i) { + *raw_acc_i = iqacc_i; + } + if (raw_acc_q) { + *raw_acc_q = iqacc_q; + } + + iqacc_i = iqacc_i >> rshiftlen; + iqacc_q = iqacc_q >> rshiftlen; + + uint64_t pwr64 = (int64_t)iqacc_i * (int64_t)iqacc_i + (int64_t)iqacc_q * (int64_t)iqacc_q; + + if ((pwr64 >> 32) != 0) { + printf(prefix "overflow occurred\r\n"); + } + + return (uint32_t)(pwr64 & 0xffffffff); +} + +void rfc_pm_stop() { + RF->dfe_ctrl_6.rx_pm_en = 0; + RF->dfe_ctrl_6.rx_pm_freqshift_en = 0; +} + +void rfc_hwctrl_txrfgain(uint8_t hwctrl_on) { + RF->rfctrl_hw_en.tx_gain_ctrl_hw = hwctrl_on; +} + +void rfc_hwctrl_rxgain(uint8_t hwctrl_on) { + RF->rfctrl_hw_en.rx_gain_ctrl_hw = hwctrl_on; +} + +void rfc_hwctrl_txdvga(uint8_t hwctrl_on) { + RF->dfe_ctrl_0.tx_dvga_gain_ctrl_hw = hwctrl_on; +} + +void rfc_hwctrl_calparam(uint8_t hwctrl_on) { + RF->rfctrl_hw_en.trxcal_ctrl_hw = hwctrl_on; +} + +void rfc_fsm_force(uint8_t state) { + if (state != RFC_FSM_FORCE_OFF) { + RF->rf_fsm_ctrl2.rf_fsm_st_dbg = state; + wait_us(20); + RF->rf_fsm_ctrl2.rf_fsm_st_dbg_en = 1; + } else { + RF->rf_fsm_ctrl2.rf_fsm_st_dbg_en = 0; + } +} + +void rfc_rc_fsm_force(uint8_t state) { + if (state == RFC_FSM_FORCE_OFF) { + RF->rf_fsm_ctrl_hw.rf_rc_state_dbg = 0; + wait_us(20); + RF->rf_fsm_ctrl_hw.rf_rc_state_dbg_en = 0; + } else { + RF->rf_fsm_ctrl_hw.rf_rc_state_dbg = state; + wait_us(20); + RF->rf_fsm_ctrl_hw.rf_rc_state_dbg_en = 1; + } +} + +void rfc_coex_force_to(uint32_t force_enable, uint32_t bbmode) { + // reset rf_fsm, fpga_fsm, state_cci + RF->rf_fsm_ctrl_hw.rf_fsm_ctrl_en = 0; + + wait_us(10); + + // force coex + RF->rfif_dfe_ctrl0.bbmode_4s = bbmode; + RF->rfif_dfe_ctrl0.bbmode_4s_en = force_enable ? 1 : 0; + + wait_us(10); + + // start fsm + RF->rf_fsm_ctrl_hw.rf_fsm_ctrl_en = 1; +} + +void rfc_dump() { + struct rfc_status_tag *p_test_read; + uint32_t test_read[2]; + static char* rc_state_str[8] = { + "RC_IDLE", + "RC_RX2ON", + "RC_TX2ON", + "RC_RXON", + "RC_TX2PAON", + "RC_TXPAON", + "UNKNOWN", + "UNKNOWN" + }; + static char* rf_state_str[8] = { + "RF_PD", + "RF_SB", + "RF_LO", + "RF_RX", + "RF_TX", + "RF_T2RI", + "RF_R2T", + "RF_MS" + }; + + + RF->rfif_dfe_ctrl0.test_sel = 1; + test_read[0] = RF->rfif_test_read.value; + + RF->rfif_dfe_ctrl0.test_sel = 2; + test_read[1] = RF->rfif_test_read.value; + + p_test_read = (struct rfc_status_tag*)test_read; + + printf("******************************** [RFC DUMP START] *****************************\r\n"); + printf(" rc_state : %s\r\n", rc_state_str[p_test_read->rf_rc_state]); + printf(" rf_state : %s\r\n", rf_state_str[p_test_read->rf_fsm_state]); + printf(" fsm_pu_lna : %d\r\n", p_test_read->fsm_pu_lna ); + printf(" fsm_pu_rmxgm : %d\r\n", p_test_read->fsm_pu_rmxgm ); + printf(" fsm_pu_rmx : %d\r\n", p_test_read->fsm_pu_rmx ); + printf(" fsm_pu_rbb : %d\r\n", p_test_read->fsm_pu_rbb ); + printf(" fsm_pu_pkdet : %d\r\n", p_test_read->fsm_pu_pkdet ); + printf(" fsm_pu_adc : %d\r\n", p_test_read->fsm_pu_adc ); + printf(" fsm_trsw_en : %d\r\n", p_test_read->fsm_trsw_en ); + printf(" fsm_pu_dac : %d\r\n", p_test_read->fsm_pu_dac ); + printf(" fsm_pu_tosdac : %d\r\n", p_test_read->fsm_pu_tosdac); + printf(" fsm_pu_rxbuf : %d\r\n", p_test_read->fsm_pu_rxbuf ); + printf(" fsm_pu_txbuf : %d\r\n", p_test_read->fsm_pu_txbuf ); + + printf("\r\n\r\n"); + printf(" tx_gain_ctrl_hw : %ld\r\n", RF->rfctrl_hw_en.tx_gain_ctrl_hw); + printf(" rx_gain_ctrl_hw : %ld\r\n", RF->rfctrl_hw_en.rx_gain_ctrl_hw); + printf(" trxcal_ctrl_hw : %ld\r\n", RF->rfctrl_hw_en.trxcal_ctrl_hw); + printf(" lo_ctrl_hw : %ld\r\n", RF->rfctrl_hw_en.lo_ctrl_hw); + printf(" lna_ctrl_hw : %ld\r\n", RF->rfctrl_hw_en.lna_ctrl_hw); + printf(" pu_ctrl_hw : %ld\r\n", RF->rfctrl_hw_en.pu_ctrl_hw); + + printf("\r\n\r\n"); + printf(" rf_lo_vco_freq_cw_hw : %ld\r\n", RF->vco1.lo_vco_freq_cw_hw); + printf(" rf_lo_vco_idac_cw_hw : %ld\r\n", RF->vco1.lo_vco_idac_cw_hw); + printf(" rf_lo_sdmin_hw : %ld\r\n", RF->sdm3.lo_sdmin_hw); + printf(" rf_ch_ind_wifi : %ld\r\n", RF->rf_fsm_ctrl0.rf_ch_ind_wifi); + + + if (RF->rf_fsm_ctrl_sw.lo_unlocked) { + printf("rf_lo_unlocked_getf = 1\r\n"); + printf("rf_lo_unlocked_getf (after csd reset) = "); + for (int i = 0; i < 8; i++) { + RF->pfdcp.lo_pfd_rst_csd = 1; + wait_us(10); + RF->pfdcp.lo_pfd_rst_csd = 0; + wait_us(10); + printf("%ld", RF->rf_fsm_ctrl_sw.lo_unlocked); + } + printf("\r\n"); + } + else { + printf("rf_lo_unlocked_getf = 0\r\n"); + } + + printf("******************************** [RFC DUMP END] *****************************\r\n"); + +} + +_Bool rfc_config_power_ble(int32_t pwr_dbm) { + int i2 = 0; + if ((uint32_t)pwr_dbm < 16) { + if (pwr_dbm < 4) { + RF->pa1.pa_ib_fix = 1; + RF->pa1.pa_half_on = 1; + RF->pa1.pa_vbcas = 4; + RF->pa1.pa_vbcore = 9; + RF->pa1.pa_etb_en = 0; // weird, this 9 will always be 0 + RF->tmx.tmx_cs = 5; + RF->trx_gain1.gc_tbb = 2; + RF->trx_gain1.gc_tmx = 5; + i2 = pwr_dbm * 4 - 18; + } else { + if (pwr_dbm < 7) { + RF->pa1.pa_ib_fix = 1; + RF->pa1.pa_half_on = 1; + RF->pa1.pa_vbcas = 4; + RF->pa1.pa_vbcore = 9; + RF->pa1.pa_etb_en = 0; // weird, this 9 will always be 0 + RF->tmx.tmx_cs = 5; + RF->trx_gain1.gc_tbb = 2; + RF->trx_gain1.gc_tmx = 7; + i2 = pwr_dbm * 4 - 30; + } else { + if (pwr_dbm < 10) { + RF->pa1.pa_ib_fix = 1; + RF->pa1.pa_half_on = 1; + RF->pa1.pa_vbcas = 4; + + RF->pa1.pa_vbcore = 9; + RF->pa1.pa_etb_en = 0; // weird, this 9 will always be 0 + + RF->tmx.tmx_cs = 5; + RF->trx_gain1.gc_tbb = 3; + RF->trx_gain1.gc_tmx = 7; + i2 = pwr_dbm - 10; + } else { + if (pwr_dbm < 12) { + RF->pa1.pa_ib_fix = 1; + RF->pa1.pa_half_on = 1; + RF->pa1.pa_vbcas = 4; + + RF->pa1.pa_vbcore = 9; + RF->pa1.pa_etb_en = 0; // weird, this 9 will always be 0 + + RF->tmx.tmx_cs = 5; + RF->trx_gain1.gc_tbb = 4; + RF->trx_gain1.gc_tmx = 7; + i2 = pwr_dbm - 12; + } else { + RF->pa1.pa_ib_fix = 1; + RF->pa1.pa_half_on = 1; + RF->pa1.pa_vbcas = 4; + + RF->pa1.pa_vbcore = 9; + RF->pa1.pa_etb_en = 0; // weird, this 9 will always be 0 + + RF->tmx.tmx_cs = 5; + RF->trx_gain1.gc_tbb = 6; + RF->trx_gain1.gc_tmx = 7; + i2 = pwr_dbm - 15; + } + } + i2 = i2 << 2; + } + } + uint32_t u2 = i2 - 1; + RF->dfe_ctrl_18.tx_dvga_gain_qdb_ble_gc0 = u2 & 0x7f; + RF->dfe_ctrl_18.tx_dvga_gain_qdb_ble_gc1 = u2 & 0x7f; + RF->dfe_ctrl_18.tx_dvga_gain_qdb_ble_gc2 = u2 & 0x7f; + } +} + + + + +static void _set_rfc(uint32_t xtalfreq_hz) { + xtalfreq_MHz = xtalfreq_hz / 1000000; + float xtal_MHz = xtalfreq_hz / 1000000; + uint32_t lo_center_freq_mhz; + /// _calc_sdm_params + if (xtalfreq_hz == 40000000) { + lo_center_freq_mhz = 2430.0; + } else { + lo_center_freq_mhz = 2448.0; + } + RF->lo_sdm_ctrl_hw5.lo_center_freq_mhz = lo_center_freq_mhz; //??? + uint32_t lo_sdmin_center = _calc_sdm_cw(xtal_MHz, lo_center_freq_mhz); + uint32_t lo_sdmin_1m = _calc_sdm_cw(xtal_MHz, 1.0); + uint32_t lo_sdmin_if = _calc_sdm_cw(xtal_MHz, 1.25); + RF->lo_sdm_ctrl_hw6.lo_sdmin_center = lo_sdmin_center; + RF->lo_sdm_ctrl_hw7.lo_sdmin_1m = lo_sdmin_1m; + RF->lo_sdm_ctrl_hw8.lo_sdmin_if = lo_sdmin_if; + + union { + uint8_t seq[2][2]; + uint32_t val; + } lo_cw = {.val = 0}; + volatile uint32_t *ptr = (volatile uint32_t *)&(RF->lo_cal_ctrl_hw1); + for (int freq = 2404, i = 0; freq <= 2484; freq += 4, i += 1) { + int freq_cw = rf_pri_get_vco_freq_cw(freq); + int idac_cw = rf_pri_get_vco_idac_cw(freq); + if (freq == 2404) freq_cw += 1; + lo_cw.seq[i&1][0] = idac_cw; + lo_cw.seq[i&1][1] = freq_cw; + if ((freq == 2484) || (i&1)) { + *ptr = lo_cw.val; + lo_cw.val = 0; + ptr++; + } + } + + _sync_tx_power_offset(); + + // configure rf_fsm related params + RF->rf_fsm_ctrl_hw.rf_rc_state_dbg_en = 0; + RF->rf_fsm_ctrl2.rf_fsm_st_dbg_en = 0; + RF->rf_fsm_ctrl1.rf_fsm_lo_time = 0x1040; + RF->rf_fsm_ctrl_hw.rf_fsm_ctrl_en = 1; + + // configure tx gain control + RF->rfctrl_hw_en.tx_gain_ctrl_hw = 1; + RF->dfe_ctrl_0.tx_dvga_gain_ctrl_hw = 1; + RF->dfe_ctrl_0.tx_dvga_gain_qdb = 0; + + // configure rf compensation paramas + // turn off trxcal if ROSDAC table changes vs gain to prevent pkdet false triggers + // caused by the transient response of ROSDAC + RF->rfctrl_hw_en.trxcal_ctrl_hw = 1; + + // configure rx gain control + RF->rfctrl_hw_en.rx_gain_ctrl_hw = 1; + +} + +static void _set_mdm() { + AGC->rc218.txhbf20coeffsel = 0; + MDM->r3030 = 0; + MDM->r3034 = 0xa027f7f; + MDM->r3038 = 0x23282317; + MDM->r303c = 0x7f020a17; + MDM->r3040 = 0x7f; +} + + + + + +static void wait_us(uint32_t us) +{ + volatile uint32_t n; + us = (us >= (1<<24)-1) ? (1<<24)-1 : us; + // if (us < 2) { + // return; + // } + // else + { + n = us << 4; + while(n--); + } +} + +__attribute__((unused)) static void wait_ms(uint32_t ms) +{ + wait_us(1000*ms); +} + +static void _set_rfc_powercontrol(uint32_t pc_mode) { + RF->pa1.pa_ib_fix = 0; + RF->tmx.tmx_cs = 6; + switch (pc_mode) { + case RFC_PC_AUTO: + RF->pa_reg_ctrl_hw2.pa_vbcore_11b = 0xf; + RF->pa_reg_ctrl_hw1.pa_vbcore_11n = 0xa; + RF->pa_reg_ctrl_hw2.pa_vbcore_11g = 0xa; + + RF->pa_reg_ctrl_hw2.pa_vbcas_11b = 5; + RF->pa_reg_ctrl_hw1.pa_vbcas_11n = 5; + RF->pa_reg_ctrl_hw2.pa_vbcas_11g = 5; + + RF->pa_reg_ctrl_hw2.pa_iet_11b = 7; + RF->pa_reg_ctrl_hw1.pa_iet_11n = 5; + RF->pa_reg_ctrl_hw2.pa_iet_11g = 5; + case RFC_PC_WLAN_11B: + case RFC_PC_BT_BLE: + RF->pa1.pa_vbcore = 0xf; + RF->pa1.pa_vbcas = 5; + RF->pa1.pa_iet = 7; + break; + case RFC_PC_WLAN_11N: + case RFC_PC_WLAN_11G: + RF->pa1.pa_vbcore = 0xa; + RF->pa1.pa_vbcas = 5; + RF->pa1.pa_iet = 5; + break; + } + RF->trx_gain1.gc_tbb_boost = 0; + RF->trx_gain1.gc_tbb = 6; + RF->trx_gain1.gc_tmx = 5; + RF->adda1.dac_bias_sel = 1; +} + +static void _set_rf_channel_sw(uint32_t channel_freq) { + uint32_t sdmin = (uint32_t)(channel_freq*4.0/3/xtalfreq_MHz*(1<<22)); + + RF->rfctrl_hw_en.lo_ctrl_hw = 0; + RF->rfctrl_hw_en.sdm_ctrl_hw = 0; + RF->pucr1.pu_vco = 1; + RF->pucr1.pu_fbdv = 1; + RF->pucr1.pu_pfd = 1; + RF->pucr1.pu_osmx = 1; + RF->rfctrl_hw_en.pu_ctrl_hw = 0; + + // set channel + // rf_lo_fbdv_halfstep_en_setf(1); + RF->vco1.lo_vco_freq_cw = rf_pri_get_vco_freq_cw(channel_freq); + RF->vco1.lo_vco_idac_cw = rf_pri_get_vco_idac_cw(channel_freq); + RF->lodist.lo_osmx_cap = rf_pri_get_vco_freq_cw(channel_freq) >> 4; + + RF->sdm2.lo_sdmin = sdmin; + RF->sdm1.lo_sdm_bypass = 0; + + // wait channel lock + do { + RF->fbdv.lo_fbdv_rst = 1; + wait_us(10); + RF->fbdv.lo_fbdv_rst = 0; + wait_us(50); + RF->pfdcp.lo_pfd_rst_csd = 1; + wait_us(10); + RF->pfdcp.lo_pfd_rst_csd = 0; + wait_us(50); + } while (0); +} \ No newline at end of file diff --git a/src/bl602_wifi/phyif_utils.c b/src/bl602_wifi/driver/phyif/phyif_utils.c similarity index 98% rename from src/bl602_wifi/phyif_utils.c rename to src/bl602_wifi/driver/phyif/phyif_utils.c index 92e0623..6715d87 100644 --- a/src/bl602_wifi/phyif_utils.c +++ b/src/bl602_wifi/driver/phyif/phyif_utils.c @@ -1,4 +1,4 @@ -#include "phyif_utils.h" +#include typedef struct { uint32_t leg_length:12; // +0 diff --git a/src/bl602_wifi/phy.h b/src/bl602_wifi/phy.h deleted file mode 100644 index db83a71..0000000 --- a/src/bl602_wifi/phy.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _PHY_H_ -#define _PHY_H_ -#include -struct phy_channel_info { - uint32_t info1; // +0 - uint32_t info2; // +4 -}; // :97:8 -#endif \ No newline at end of file diff --git a/src/bl602_wifi/rfc_bl602.c b/src/bl602_wifi/rfc_bl602.c deleted file mode 100644 index c16622e..0000000 --- a/src/bl602_wifi/rfc_bl602.c +++ /dev/null @@ -1,169 +0,0 @@ - -#include "rfc_bl602.h" -#include "bl602_rf_private.h" -#include "utils.h" - -#include - -void rfc_apply_tx_power_offset(uint8_t channel, int8_t *power_offset){ - rf_pri_update_tx_power_offset(channel, power_offset); - uint32_t rfg_index, dg; - rf_pri_query_txgain_table(0, &rfg_index, &dg); - RF->dfe_ctrl_16.rf_tbb_ind_gc0 = rfg_index & 7; - RF->dfe_ctrl_12.tx_dvga_gain_qdb_gc0 = dg; - rf_pri_query_txgain_table(1, &rfg_index, &dg); - RF->dfe_ctrl_16.rf_tbb_ind_gc1 = rfg_index & 7; - RF->dfe_ctrl_12.tx_dvga_gain_qdb_gc1 = dg; - rf_pri_query_txgain_table(2, &rfg_index, &dg); - RF->dfe_ctrl_16.rf_tbb_ind_gc2 = rfg_index & 7; - RF->dfe_ctrl_12.tx_dvga_gain_qdb_gc2 = dg; - rf_pri_query_txgain_table(3, &rfg_index, &dg); - RF->dfe_ctrl_16.rf_tbb_ind_gc3 = rfg_index & 7; - RF->dfe_ctrl_12.tx_dvga_gain_qdb_gc3 = dg; - rf_pri_query_txgain_table(4, &rfg_index, &dg); - RF->dfe_ctrl_16.rf_tbb_ind_gc4 = rfg_index & 7; - RF->dfe_ctrl_13.tx_dvga_gain_qdb_gc4 = dg; - rf_pri_query_txgain_table(5, &rfg_index, &dg); - RF->dfe_ctrl_16.rf_tbb_ind_gc5 = rfg_index & 7; - RF->dfe_ctrl_13.tx_dvga_gain_qdb_gc5 = dg; - rf_pri_query_txgain_table(6, &rfg_index, &dg); - RF->dfe_ctrl_16.rf_tbb_ind_gc6 = rfg_index & 7; - RF->dfe_ctrl_13.tx_dvga_gain_qdb_gc6 = dg; - rf_pri_query_txgain_table(7, &rfg_index, &dg); - RF->dfe_ctrl_16.rf_tbb_ind_gc7 = rfg_index & 7; - RF->dfe_ctrl_13.tx_dvga_gain_qdb_gc7 = dg; - rf_pri_query_txgain_table(8, &rfg_index, &dg); - RF->dfe_ctrl_17.rf_tbb_ind_gc8 = rfg_index & 7; - RF->dfe_ctrl_14.tx_dvga_gain_qdb_gc8 = dg; - rf_pri_query_txgain_table(9, &rfg_index, &dg); - RF->dfe_ctrl_17.rf_tbb_ind_gc9 = rfg_index & 7; - RF->dfe_ctrl_14.tx_dvga_gain_qdb_gc9 = dg; - rf_pri_query_txgain_table(10, &rfg_index, &dg); - RF->dfe_ctrl_17.rf_tbb_ind_gc10 = rfg_index & 7; - RF->dfe_ctrl_14.tx_dvga_gain_qdb_gc10 = dg; - rf_pri_query_txgain_table(11, &rfg_index, &dg); - RF->dfe_ctrl_17.rf_tbb_ind_gc11 = rfg_index & 7; - RF->dfe_ctrl_14.tx_dvga_gain_qdb_gc11 = dg; - rf_pri_query_txgain_table(12, &rfg_index, &dg); - RF->dfe_ctrl_17.rf_tbb_ind_gc12 = rfg_index & 7; - RF->dfe_ctrl_15.tx_dvga_gain_qdb_gc12 = dg; - rf_pri_query_txgain_table(13, &rfg_index, &dg); - RF->dfe_ctrl_17.rf_tbb_ind_gc13 = rfg_index & 7; - RF->dfe_ctrl_15.tx_dvga_gain_qdb_gc13 = dg; - rf_pri_query_txgain_table(14, &rfg_index, &dg); - RF->dfe_ctrl_17.rf_tbb_ind_gc14 = rfg_index & 7; - RF->dfe_ctrl_15.tx_dvga_gain_qdb_gc14 = dg; - rf_pri_query_txgain_table(15, &rfg_index, &dg); - RF->dfe_ctrl_17.rf_tbb_ind_gc15 = rfg_index & 7; - RF->dfe_ctrl_15.tx_dvga_gain_qdb_gc15 = dg; - -} - - - -void rfc_apply_tx_dvga(int8_t *dvga_qdb) { - RF->dfe_ctrl_12.tx_dvga_gain_qdb_gc0 = dvga_qdb[0]; - RF->dfe_ctrl_12.tx_dvga_gain_qdb_gc1 = dvga_qdb[1]; - RF->dfe_ctrl_12.tx_dvga_gain_qdb_gc2 = dvga_qdb[2]; - RF->dfe_ctrl_12.tx_dvga_gain_qdb_gc3 = dvga_qdb[3]; - - RF->dfe_ctrl_13.tx_dvga_gain_qdb_gc4 = dvga_qdb[4]; - RF->dfe_ctrl_13.tx_dvga_gain_qdb_gc5 = dvga_qdb[5]; - RF->dfe_ctrl_13.tx_dvga_gain_qdb_gc6 = dvga_qdb[6]; - RF->dfe_ctrl_13.tx_dvga_gain_qdb_gc7 = dvga_qdb[7]; - - RF->dfe_ctrl_14.tx_dvga_gain_qdb_gc8 = dvga_qdb[8]; - RF->dfe_ctrl_14.tx_dvga_gain_qdb_gc9 = dvga_qdb[9]; - RF->dfe_ctrl_14.tx_dvga_gain_qdb_gc10 = dvga_qdb[10]; - RF->dfe_ctrl_14.tx_dvga_gain_qdb_gc11 = dvga_qdb[11]; - - RF->dfe_ctrl_15.tx_dvga_gain_qdb_gc12 = dvga_qdb[12]; - RF->dfe_ctrl_15.tx_dvga_gain_qdb_gc13 = dvga_qdb[13]; - RF->dfe_ctrl_15.tx_dvga_gain_qdb_gc14 = dvga_qdb[14]; - RF->dfe_ctrl_15.tx_dvga_gain_qdb_gc15 = dvga_qdb[15]; -} - -void rfc_coex_force_to(uint32_t force_enable, uint32_t bbmode) { - RF->rf_fsm_ctrl_hw.rf_fsm_ctrl_en = 0; - wait_us(10); - RF->rfif_dfe_ctrl0.bbmode_4s = bbmode & 1; - RF->rfif_dfe_ctrl0.bbmode_4s_en = (force_enable != 0); -} - -void rfc_config_channel(uint32_t channel_freq) { - RF->rfif_dig_ctrl.rfif_int_lo_unlocked_mask = 1; - RF->rfctrl_hw_en.lo_ctrl_hw = 1; - RF->rfctrl_hw_en.sdm_ctrl_hw = 1; - RF->rfctrl_hw_en.pu_ctrl_hw = 1; - RF->rf_fsm_ctrl0.rf_ch_ind_wifi = channel_freq & 0xfff; - RF->rf_fsm_ctrl1.rf_fsm_lo_rdy_rst = 1; - wait_us(10); - RF->rf_fsm_ctrl1.rf_fsm_lo_rdy_rst = 0; - wait_us(10); - RF->rf_fsm_ctrl_hw.rf_fsm_ctrl_en = 0; - wait_us(10); - RF->rf_fsm_ctrl_hw.rf_fsm_ctrl_en = 1; - wait_us(10); - RF->rf_fsm_ctrl2.rf_fsm_st_dbg = 1; - wait_us(10); - RF->rf_fsm_ctrl2.rf_fsm_st_dbg_en = 1; - wait_us(10); - RF->rf_fsm_ctrl2.rf_fsm_st_dbg = 2; - wait_us(100); - RF->rf_fsm_ctrl2.rf_fsm_st_dbg_en = 0; - wait_us(10); - _print_channel_info(); - rf_pri_update_param(channel_freq); - uint8_t ncf_on; - int32_t ncf_freq_Hz; - rf_pri_get_notch_param(channel_freq, &ncf_on, (int32_t *)&ncf_freq_Hz); - double freq = ncf_freq_Hz; - freq /= 40000000.0; - freq *= 256.0; - freq += 0.5; - int32_t new_freq = freq; - rfc_rxdfe_set_notch0(ncf_on, 1, new_freq); - RF->rfif_dig_ctrl.rfif_int_lo_unlocked_mask = 0; -} - -uint32_t rfc_get_power_level(uint32_t formatmod, int32_t power) { - if (formatmod > 2) - formatmod = 0; - return rf_pri_get_txgain_index(power, formatmod) << 2; -} - -void rfc_init(uint32_t xtalfreq_hz) { - RF->rfif_dfe_ctrl0.bbmode_4s = 0; - RF->rfif_dfe_ctrl0.bbmode_4s_en = 1; - int xtal_mode = 2; - if (xtalfreq_hz != 32000000) { - if (xtalfreq_hz < 0x1e84801) { - xtal_mode = 0; - if (xtalfreq_hz == 24000000) { - xtal_mode = 1; - } else { - xtal_mode = 4; - } - } else { - if (xtalfreq_hz != 40000000) { - xtal_mode = 5; - if (xtalfreq_hz != 52000000) { - if (xtalfreq_hz == 38400000) { - xtal_mode = 3; - } else { - xtal_mode = 4; - } - } - } - } - } -} - -void _print_channel_info() { - for (int i = 0; i < 8; i++) { - wait_us(1000); - } - for (int i = 0; i < 8; i++) { - wait_us(1000); - } -} \ No newline at end of file diff --git a/src/bl602_wifi/rfc_bl602.h b/src/bl602_wifi/rfc_bl602.h deleted file mode 100644 index 51987a9..0000000 --- a/src/bl602_wifi/rfc_bl602.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _RFC_BL602_H_ -#define _RFC_BL602_H_ -#include -uint32_t rfc_get_power_level(uint32_t formatmod, int32_t power); // :1479:10 -void rfc_apply_tx_power_offset(uint8_t channel, int8_t *power_offset); // :1643:6 -void rfc_config_channel(uint32_t channel_freq); -void rfc_apply_tx_dvga(int8_t *dvga_qdb); -void _print_channel_info(); -#endif \ No newline at end of file diff --git a/src/bl602_wifi/assert.h b/src/include/assert.h similarity index 100% rename from src/bl602_wifi/assert.h rename to src/include/assert.h diff --git a/src/include/bl602_wifi/phy_rf/bl602_rf_calib_data.h b/src/include/bl602_wifi/phy_rf/bl602_rf_calib_data.h new file mode 100644 index 0000000..72faa65 --- /dev/null +++ b/src/include/bl602_wifi/phy_rf/bl602_rf_calib_data.h @@ -0,0 +1,58 @@ +#ifndef _BL602_RF_CALIB_DATA_H_ +#define _BL602_RF_CALIB_DATA_H_ +#include +typedef struct { + uint32_t gpadc_oscode:12; // +0 + uint32_t rx_offset_i:10; // +0 + uint32_t rx_offset_q:10; // +0 + uint32_t rbb_cap1_fc_i:6; // +4 + uint32_t rbb_cap1_fc_q:6; // +4 + uint32_t rbb_cap2_fc_i:6; // +4 + uint32_t rbb_cap2_fc_q:6; // +4 + uint32_t tx_dc_comp_i:12; // +8 + uint32_t tx_dc_comp_q:12; // +8 + uint32_t tmx_cs:3; // +8 + uint32_t txpwr_att_rec:3; // +8 + uint32_t pa_pwrmx_osdac:4; // +12 + uint32_t tmx_csh:3; // +12 + uint32_t tmx_csl:3; // +12 + uint32_t tsen_refcode_rfcal:12; // +12 + uint32_t tsen_refcode_corner:12; // +16 + uint32_t rc32k_code_fr_ext:10; // +16 + uint32_t rc32m_code_fr_ext:8; // +16 + uint32_t saradc_oscode:10; // +20 + uint16_t fcal_4osmx:4; // +20 +} rf_calib1_tag; // :37:3 + +typedef struct { + uint16_t fcal:8; // +0 + uint16_t acal:5; // +0 +} rf_calib2_tag; // :44:3 + +typedef struct { + uint32_t rosdac_i:6; // +0 + uint32_t rosdac_q:6; // +0 + uint32_t rx_iq_gain_comp:11; // +0 + uint32_t rx_iq_phase_comp:10; // +4 +} rf_calib3_tag; // :53:3 + +typedef struct { + uint32_t tosdac_i:6; // +0 + uint32_t tosdac_q:6; // +0 + uint32_t tx_iq_gain_comp:11; // +0 + uint32_t tx_iq_phase_comp:10; // +4 +} rf_calib4_tag; // :62:3 + +typedef volatile struct { + uint32_t inited; // +0 + rf_calib1_tag cal; // +4 + rf_calib2_tag lo[21]; // +28 + rf_calib3_tag rxcal[4]; // +72 + rf_calib4_tag txcal[8]; // +104 +} rf_calib_data_tag; // :72:3 + +extern rf_calib_data_tag *rf_calib_data; // :75:27 +// void rf_pri_init_calib_mem(void); +// unused + +#endif \ No newline at end of file diff --git a/src/bl602_wifi/bl602_rf_private.h b/src/include/bl602_wifi/phy_rf/bl602_rf_private.h similarity index 62% rename from src/bl602_wifi/bl602_rf_private.h rename to src/include/bl602_wifi/phy_rf/bl602_rf_private.h index 27a630f..0ac7f1e 100644 --- a/src/bl602_wifi/bl602_rf_private.h +++ b/src/include/bl602_wifi/phy_rf/bl602_rf_private.h @@ -1,7 +1,7 @@ #ifndef _BL602_RF_PRIVATE_H_ #define _BL602_RF_PRIVATE_H_ #include - +#define RF_PRIVATE_PRESENT 1 struct anon_struct1 { uint32_t index; int32_t dvga; @@ -78,4 +78,79 @@ void rf_pri_update_power_offset(int32_t * power_offset); void rf_pri_update_tx_power_offset(uint8_t channel, int8_t * power_offset); void rf_pri_update_txgain_tempos(int16_t tempos); void rf_pri_xtalfreq(uint32_t xtalfreq); + +enum { + E_RF_XTAL_24M = 0, + E_RF_XTAL_26M = 1, + E_RF_XTAL_32M = 2, + E_RF_XTAL_38M4 = 3, + E_RF_XTAL_40M = 4, + E_RF_XTAL_52M = 5, +}; + +enum +{ + E_RF_CHANNEL_2404M = 0, + E_RF_CHANNEL_2408M, + E_RF_CHANNEL_2412M, + E_RF_CHANNEL_2416M, + E_RF_CHANNEL_2420M, + E_RF_CHANNEL_2424M, + E_RF_CHANNEL_2428M, + E_RF_CHANNEL_2432M, + E_RF_CHANNEL_2436M, + E_RF_CHANNEL_2440M, + E_RF_CHANNEL_2444M, + E_RF_CHANNEL_2448M, + E_RF_CHANNEL_2452M, + E_RF_CHANNEL_2456M, + E_RF_CHANNEL_2460M, + E_RF_CHANNEL_2464M, + E_RF_CHANNEL_2468M, + E_RF_CHANNEL_2472M, + E_RF_CHANNEL_2476M, + E_RF_CHANNEL_2480M, + E_RF_CHANNEL_2484M, + E_RF_CHANNEL_NUM +}; + +enum { + E_RF_BRANCH_I = 0, + E_RF_BRANCH_Q = 1, + E_RF_GAIN = 2, + E_RF_PHASE = 3 +}; + +enum { + E_RF_MODE_11B = 0, + E_RF_MODE_11G = 1, + E_RF_MODE_11N = 2, +}; + +enum { + E_RF_GC_TBB_0DB = 0, + E_RF_GC_TBB_6DB = 1, + E_RF_GC_TBB_12DB = 2, + E_RF_GC_TBB_18DB = 3, + E_RF_GC_TBB_24DB = 4 +}; + +enum { + E_RF_MODE_IDLE = 0, + E_RF_MODE_TX, + E_RF_MODE_RX, + E_RF_MODE_ROSCAL, + E_RF_MODE_RCCAL, + E_RF_MODE_TXCAL, + E_RF_MODE_LO_ACAL, + E_RF_MODE_LO_FCAL +}; + +enum { + E_RF_RXCAL_GAIN_CNT = 4, + E_RF_TXCAL_GAIN_CNT = 8, + E_RF_TXPWR_TBL_CNT = 16, +}; + + #endif \ No newline at end of file diff --git a/src/bl602_wifi/hal_desc.h b/src/include/bl602_wifi/phy_rf/hal_desc.h similarity index 91% rename from src/bl602_wifi/hal_desc.h rename to src/include/bl602_wifi/phy_rf/hal_desc.h index 849e16b..936b96f 100644 --- a/src/bl602_wifi/hal_desc.h +++ b/src/include/bl602_wifi/phy_rf/hal_desc.h @@ -2,7 +2,18 @@ #ifndef _HAL_DESC_H_ #define _HAL_DESC_H_ #include -#include "phy.h" +#include + +/// 20 MHz bandwidth +#define BW_20MHZ 0 +/// 40 MHz bandwidth +#define BW_40MHZ 1 +/// 80 MHz bandwidth +#define BW_80MHZ 2 +/// 160 or 80+80 MHz bandwidth +#define BW_160MHZ 3 + + struct tx_policy_tbl { uint32_t upatterntx; // +0 uint32_t phycntrlinfo1; // +4 diff --git a/src/include/bl602_wifi/phy_rf/phy.h b/src/include/bl602_wifi/phy_rf/phy.h new file mode 100644 index 0000000..2a646a4 --- /dev/null +++ b/src/include/bl602_wifi/phy_rf/phy.h @@ -0,0 +1,74 @@ +#ifndef _PHY_H_ +#define _PHY_H_ +#include + + +/// Invalid value for some octet parameters reserved for the future +#define PHY_UNUSED 0xFF + +/// Maximum number of words in the configuration buffer +#define PHY_CFG_BUF_SIZE 16 + + +/* + * DEFINES + **************************************************************************************** + */ +/// Invalid value for some octet parameters reserved for the future +#define PHY_UNUSED 0xFF + +/// Maximum number of words in the configuration buffer +#define PHY_CFG_BUF_SIZE 16 + +enum +{ + /// 2.4GHz Band + PHY_BAND_2G4, + /// 5GHz band + PHY_BAND_5G, + /// Number of bands + PHY_BAND_MAX, +}; + +enum +{ + PHY_CHNL_BW_20, + PHY_CHNL_BW_40, + PHY_CHNL_BW_80, + PHY_CHNL_BW_160, + PHY_CHNL_BW_80P80, + PHY_CHNL_BW_OTHER, +}; + +enum +{ + /// Primary radar detection chain (i.e for the operating channel) + PHY_PRIM, + /// Secondary radar detection chain + PHY_SEC, +}; + +/// Structure containing the information about the PHY channel that was used for this RX +struct phy_channel_info +{ + /// PHY channel information 1 + uint32_t info1; + /// PHY channel information 2 + uint32_t info2; +}; + +struct phy_radar_pulse +{ + /// In our PHY a radar pulse is only one 32-bit word + uint32_t pulse; +}; + +/// Structure containing the parameters of the PHY configuration +struct phy_cfg_tag +{ + /// Buffer containing the parameters specific for the PHY used + uint32_t parameters[PHY_CFG_BUF_SIZE]; +}; + +typedef struct phy_cfg_tag phy_cfg_tag; +#endif \ No newline at end of file diff --git a/src/bl602_wifi/phy_adapt.h b/src/include/bl602_wifi/phy_rf/phy_adapt.h similarity index 98% rename from src/bl602_wifi/phy_adapt.h rename to src/include/bl602_wifi/phy_rf/phy_adapt.h index 33e074e..b5a938b 100644 --- a/src/bl602_wifi/phy_adapt.h +++ b/src/include/bl602_wifi/phy_rf/phy_adapt.h @@ -1,7 +1,7 @@ #ifndef _PHY_ADAPT_H_ #define _PHY_ADAPT_H_ #include -#include "hal_desc.h" +#include typedef struct { int8_t rssi; // +0 diff --git a/src/bl602_wifi/phy_bl602.h b/src/include/bl602_wifi/phy_rf/phy_bl602.h similarity index 87% rename from src/bl602_wifi/phy_bl602.h rename to src/include/bl602_wifi/phy_rf/phy_bl602.h index dfd8b48..d74e62a 100644 --- a/src/bl602_wifi/phy_bl602.h +++ b/src/include/bl602_wifi/phy_rf/phy_bl602.h @@ -1,25 +1,16 @@ #ifndef _PHY_BL602_H_ #include -#include "phy.h" -enum -{ - /// 2.4GHz Band - PHY_BAND_2G4, - /// 5GHz band - PHY_BAND_5G, - /// Number of bands - PHY_BAND_MAX, -}; +#include -enum -{ - PHY_CHNL_BW_20, - PHY_CHNL_BW_40, - PHY_CHNL_BW_80, - PHY_CHNL_BW_160, - PHY_CHNL_BW_80P80, - PHY_CHNL_BW_OTHER, -}; +/// Maximum output power TODO +#define PHY_BL602_MAX_PWR_24G (20) +/// Minimum output power TODO +#define PHY_BL602_MIN_PWR_24G (-6) +/// MAC core clock frequency in MHz +#define PHY_BL602_MACCORE_FREQ_MHZ (40) +/// AGC memory address and size +#define PHY_BL602_AGC_MEM_ADDR (0x54c0a000) +#define PHY_BL602_AGC_MEM_SIZE (2048) enum { @@ -28,13 +19,6 @@ enum PHY_FORMATMOD_11N, }; -typedef struct phy_cfg_tag phy_cfg_tag; - -struct phy_cfg_tag { - uint32_t parameters[16]; -}; - - struct phy_bl602_cfg_tag { uint32_t reserved; }; // :48:8 diff --git a/src/bl602_wifi/phy_hal.h b/src/include/bl602_wifi/phy_rf/phy_hal.h similarity index 100% rename from src/bl602_wifi/phy_hal.h rename to src/include/bl602_wifi/phy_rf/phy_hal.h diff --git a/src/bl602_wifi/phy_helper.h b/src/include/bl602_wifi/phy_rf/phy_helper.h similarity index 100% rename from src/bl602_wifi/phy_helper.h rename to src/include/bl602_wifi/phy_rf/phy_helper.h diff --git a/src/bl602_wifi/phy_tcal.h b/src/include/bl602_wifi/phy_rf/phy_tcal.h similarity index 100% rename from src/bl602_wifi/phy_tcal.h rename to src/include/bl602_wifi/phy_rf/phy_tcal.h diff --git a/src/bl602_wifi/phy_trpc.h b/src/include/bl602_wifi/phy_rf/phy_trpc.h similarity index 100% rename from src/bl602_wifi/phy_trpc.h rename to src/include/bl602_wifi/phy_rf/phy_trpc.h diff --git a/src/bl602_wifi/rf.h b/src/include/bl602_wifi/phy_rf/rf.h similarity index 100% rename from src/bl602_wifi/rf.h rename to src/include/bl602_wifi/phy_rf/rf.h diff --git a/src/include/bl602_wifi/phy_rf/rfc_bl602.h b/src/include/bl602_wifi/phy_rf/rfc_bl602.h new file mode 100644 index 0000000..2fa9add --- /dev/null +++ b/src/include/bl602_wifi/phy_rf/rfc_bl602.h @@ -0,0 +1,199 @@ +#ifndef _RFC_BL602_H_ +#define _RFC_BL602_H_ +#include + + +enum +{ + RFC_OFF = 0, + RFC_ON = 1 +}; + +enum +{ + RFC_PM_MUX_TO_ADC = 0, + RFC_PM_MUX_TO_IQCOMP = 1, + RFC_PM_MUX_TO_BLE = 2 +}; + +enum +{ + RFC_TXDFE_IN_MUX_TO_BB = 0, + RFC_TXDFE_IN_MUX_TO_SRAM = 1, + RFC_TXDFE_IN_MUX_TO_SINGEN = 2, + RFC_TXDFE_IN_MUX_TO_PAD = 3 +}; + +enum +{ + RFC_FSM_PD = 0, + RFC_FSM_SB = 1, + RFC_FSM_LO = 2, + RFC_FSM_RX = 3, + RFC_FSM_TX = 4, + RFC_FSM_FORCE_OFF = 15 +}; + +enum +{ + RFC_BBMODE_WLAN = 0, + RFC_BBMODE_BLE = 1 +}; + +enum +{ + RFC_SG_SINGLE_TONE = 0, + RFC_SG_TWO_TONE, + RFC_SG_RAMP +}; + +enum { + RFC_PC_AUTO = 0, + RFC_PC_WLAN_11B, + RFC_PC_WLAN_11G, + RFC_PC_WLAN_11N, + RFC_PC_BT_BLE +}; + +enum { + RFC_FORMATMOD_11B = 0, + RFC_FORMATMOD_11G = 1, + RFC_FORMATMOD_11N = 2 +}; + +enum { + RFC_BW_20M = 0, + RFC_BW_10M = 1 +}; + +void rfc_init(uint32_t xtalfreq); +void rfc_reset(); +void rfc_ver_set(uint8_t ver); // :1047:6 +void rfc_config_channel(uint32_t channel_freq); +void rfc_config_channel_sw(uint32_t channel_freq); +// void rfc_write_reg(uint32_t a, uint32_t d); +// uint32_t rfc_read_reg(uint32_t a); + +uint32_t rfc_get_power_level(uint32_t mode, int32_t power); +void rfc_wlan_mode_force(uint32_t force_mode); // :1500:6 +/* + * TXDFE DECLARATIONS + **************************************************************************************** + */ +void rfc_txdfe_start(); +void rfc_txdfe_stop(); +void rfc_txdfe_mux(int8_t signal_source); +void rfc_txdfe_set_dvga(int8_t dvga_qdb); +void rfc_txdfe_set_iqgaincomp(uint8_t en,uint16_t coeff); +void rfc_txdfe_set_iqphasecomp(uint8_t en,int16_t coeff); +void rfc_txdfe_set_dccomp(int16_t dcc_i,int16_t dcc_q); +void rfc_txdfe_set_iqswap(uint8_t swap_on); + +/* + * RXDFE DECLARATIONS + **************************************************************************************** + */ +void rfc_rxdfe_start(); +void rfc_rxdfe_stop(); +void rfc_rxdfe_set_iqgaincomp(uint8_t en,uint16_t coeff); +void rfc_rxdfe_set_iqphasecomp(uint8_t en,int16_t coeff); +void rfc_rxdfe_set_dccomp(int16_t dcc_i,int16_t dcc_q); +void rfc_rxdfe_set_iqswap(uint8_t swap_on); +void rfc_rxdfe_set_notch0(uint8_t en,uint8_t alpha,int8_t nrmfc); +void rfc_rxdfe_set_notch1(uint8_t en,uint8_t alpha,int8_t nrmfc); + +/* + * SG DECLARATIONS + **************************************************************************************** + */ +void rfc_sg_start(uint32_t inc_step,uint32_t gain_i,uint32_t gain_q,uint32_t addr_i,uint32_t addr_q); +void rfc_sg_stop(); + +/* + * PM DECLARATIONS + **************************************************************************************** + */ + +uint32_t rfc_pm_start(uint32_t insel,int32_t freq_cw,uint32_t acclen,uint32_t rshiftlen, + int32_t *raw_acc_i,int32_t *raw_acc_q); +void rfc_pm_stop(); + +/* + * HWCTRL DECLARATIONS + **************************************************************************************** + */ +void rfc_hwctrl_txrfgain(uint8_t hwctrl_on); +void rfc_hwctrl_rxgain(uint8_t hwctrl_on); +void rfc_hwctrl_txdvga(uint8_t hwctrl_on); +void rfc_hwctrl_calparam(uint8_t hwctrl_on); + +/* + * FSM DECLARATIONS + **************************************************************************************** + */ + +void rfc_fsm_force(uint8_t state); +void rfc_rc_fsm_force(uint8_t state); // :1313:6 +/* + * COEX DECLARATIONS + **************************************************************************************** + */ +void rfc_coex_force_to(uint32_t force_enable, uint32_t bbmode); + +void rfc_dump(); + +void rfc_apply_tx_power_offset(uint8_t channel, int8_t *power_offset); // :1643:6 +void rfc_config_channel(uint32_t channel_freq); +void rfc_apply_tx_dvga(int8_t *dvga_qdb); +void rfc_apply_tx_dvga_offset(int8_t offset_qdb); // :1519:6 + +void rfc_config_power(uint32_t mode, uint32_t tbb_boost, uint32_t tbb, uint32_t tmx); +_Bool rfc_config_power_ble(int32_t pwr_dbm); +void rfc_config_bandwidth(uint32_t mode); + +struct rfc_status_tag { + uint32_t pkdet_out_raw:1; // +0 + uint32_t dig_xtal_clk_dbg:1; // +0 + uint32_t clk_ble_16m_dbg:1; // +0 + uint32_t clk_rc_dbg0:1; // +0 + uint32_t clk_adcpow_dbg:1; // +0 + uint32_t clk_fetx_dbg:1; // +0 + uint32_t clk_ferx_dbg:1; // +0 + uint32_t clkpll_postdiv_outclk_dbg:1; // +0 + uint32_t clk_soc_480m_dbg:1; // +0 + uint32_t clk_soc_240m_dbg:1; // +0 + uint32_t clk_soc_192m_dbg:1; // +0 + uint32_t clk_soc_160m_dbg:1; // +0 + uint32_t clk_soc_120m_dbg:1; // +0 + uint32_t clk_soc_96m_dbg:1; // +0 + uint32_t clk_soc_80m_dbg:1; // +0 + uint32_t clk_soc_48m_dbg:1; // +0 + uint32_t clk_soc_32m_dbg:1; // +0 + uint32_t pad_pkdet_out:1; // +0 + uint32_t pad_agc_ctrl:10; // +0 + uint32_t rf_pkdet_rst_hw:1; // +0 + uint32_t rf_cbw_wifi:2; // +0 + uint32_t lo_unlocked:1; // +0 + uint32_t fsm_pu_txbuf:1; // +4 + uint32_t fsm_pu_rxbuf:1; // +4 + uint32_t fsm_pu_tosdac:1; // +4 + uint32_t fsm_pu_dac:1; // +4 + uint32_t fsm_trsw_en:1; // +4 + uint32_t fsm_pu_adc:1; // +4 + uint32_t fsm_pu_pkdet:1; // +4 + uint32_t fsm_pu_rbb:1; // +4 + uint32_t fsm_pu_rmx:1; // +4 + uint32_t fsm_pu_rmxgm:1; // +4 + uint32_t fsm_pu_lna:1; // +4 + uint32_t clk_rc_dbg2:1; // +4 + uint32_t rf_lna_ind_hw:4; // +4 + uint32_t rf_rbb_ind_hw:4; // +4 + uint32_t rf_tx_pow_lvl_hw:4; // +4 + uint32_t rf_rc_lo_rdy:1; // +4 + uint32_t rf_fsm_state:3; // +4 + uint32_t rf_rc_state:3; // +4 + uint32_t clk_rc_dbg:1; // +4 +}; // :84:8 + + +#endif \ No newline at end of file diff --git a/src/bl602_wifi/phyif_utils.h b/src/include/bl602_wifi/phyif/phyif_utils.h similarity index 100% rename from src/bl602_wifi/phyif_utils.h rename to src/include/bl602_wifi/phyif/phyif_utils.h diff --git a/src/bl602_wifi/utils.h b/src/include/utils.h similarity index 90% rename from src/bl602_wifi/utils.h rename to src/include/utils.h index 932abb2..3cbf09b 100644 --- a/src/bl602_wifi/utils.h +++ b/src/include/utils.h @@ -6,6 +6,6 @@ int puts(char *s); int printf(char *fmt,...); void* memset(void *, int, long unsigned int); void* memcpy(void*, const void*, unsigned int); -void wait_us(uint32_t us); void BL602_Delay_US(uint32_t cnt); +void BL602_Delay_MS(uint32_t cnt); #endif \ No newline at end of file From 50d981a08c6b8f0248e4d295ce08d7c9aec9fdb4 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 19 Dec 2021 03:34:44 -0600 Subject: [PATCH 061/148] add clang build option --- CMakeLists.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index be544e1..7840dc0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,15 @@ set(CMAKE_SYSTEM_PROCESSOR riscv) SET(CMAKE_CROSSCOMPILING 1) set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") +option(USE_CLANG "build application with clang" OFF) +if(USE_CLANG) + set(CMAKE_C_COMPILER clang) + set(CMAKE_C_COMPILER_TARGET "riscv32-unknown-elf") + set(CMAKE_CXX_COMPILER clang++) + set(CMAKE_CXX_COMPILER_TARGET "riscv32-unknown-elf") + set(CMAKE_TOOLCHAIN_PREFIX llvm-) +endif() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -march=rv32imfc -mabi=ilp32f") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -march=rv32imfc -mabi=ilp32f") project(bl602_re VERSION 0.1.0) From c126e6a456e9e5763343457f5cb664f8e4524304 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 19 Dec 2021 03:34:53 -0600 Subject: [PATCH 062/148] add github action --- .github/workflows/action-libbl602_wifi.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .github/workflows/action-libbl602_wifi.yml diff --git a/.github/workflows/action-libbl602_wifi.yml b/.github/workflows/action-libbl602_wifi.yml new file mode 100644 index 0000000..f367fbd --- /dev/null +++ b/.github/workflows/action-libbl602_wifi.yml @@ -0,0 +1,20 @@ +name: Compile libbl602_wifi +on: [push] +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Clang + uses: egor-tensin/setup-clang@v1 + with: + version: latest + platform: x64 + - name: Build libbl602_wifi + run: mkdir build && cmake -DUSE_CLANG=ON .. && make -j + - name: Archive artifacts + uses: actions/upload-artifact@v2 + with: + name: libbl602_wifi + path: build/src/libbl602_wifi.a + \ No newline at end of file From e85555d92b72b3e75952739f5a90532d4c33fcac Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 19 Dec 2021 03:36:30 -0600 Subject: [PATCH 063/148] update command --- .github/workflows/action-libbl602_wifi.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/action-libbl602_wifi.yml b/.github/workflows/action-libbl602_wifi.yml index f367fbd..c393cc0 100644 --- a/.github/workflows/action-libbl602_wifi.yml +++ b/.github/workflows/action-libbl602_wifi.yml @@ -11,7 +11,7 @@ jobs: version: latest platform: x64 - name: Build libbl602_wifi - run: mkdir build && cmake -DUSE_CLANG=ON .. && make -j + run: mkdir build && cd build && cmake -DUSE_CLANG=ON .. && make -j - name: Archive artifacts uses: actions/upload-artifact@v2 with: From d140eeec841c9df80c3d86033e9f8b4f6d71cab1 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 19 Dec 2021 03:38:18 -0600 Subject: [PATCH 064/148] update artifact path --- .github/workflows/action-libbl602_wifi.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/action-libbl602_wifi.yml b/.github/workflows/action-libbl602_wifi.yml index c393cc0..cc66350 100644 --- a/.github/workflows/action-libbl602_wifi.yml +++ b/.github/workflows/action-libbl602_wifi.yml @@ -16,5 +16,5 @@ jobs: uses: actions/upload-artifact@v2 with: name: libbl602_wifi - path: build/src/libbl602_wifi.a + path: src/libbl602_wifi.a \ No newline at end of file From babe32bdb8bf306d0fc296cc8f92fd999be82b9f Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 19 Dec 2021 03:42:18 -0600 Subject: [PATCH 065/148] update path --- .github/workflows/action-libbl602_wifi.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/action-libbl602_wifi.yml b/.github/workflows/action-libbl602_wifi.yml index cc66350..f5d80ef 100644 --- a/.github/workflows/action-libbl602_wifi.yml +++ b/.github/workflows/action-libbl602_wifi.yml @@ -11,10 +11,10 @@ jobs: version: latest platform: x64 - name: Build libbl602_wifi - run: mkdir build && cd build && cmake -DUSE_CLANG=ON .. && make -j + run: mkdir build && cd build && cmake -DUSE_CLANG=ON .. && make -j && cd .. - name: Archive artifacts uses: actions/upload-artifact@v2 with: name: libbl602_wifi - path: src/libbl602_wifi.a + path: build/src/bl602_wifi/libbl602_wifi.a \ No newline at end of file From 09b791626fbce34a5615c02eb456a4945a24e681 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 19 Dec 2021 03:58:09 -0600 Subject: [PATCH 066/148] add ble --- tools/inline_annotate.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/inline_annotate.py b/tools/inline_annotate.py index e3be69f..84c8bc7 100644 --- a/tools/inline_annotate.py +++ b/tools/inline_annotate.py @@ -57,8 +57,8 @@ def peek_line(f): root = CU.get_top_DIE() is_ble = 'components/network/ble/blecontroller' in root.get_full_path() is_wifi = 'bl602/bl602_wifi/' in root.get_full_path() - if ('ble' in path and not is_ble) or ('wifi' in path and not is_wifi): - continue + #if ('ble' in path and not is_ble) or ('wifi' in path and not is_wifi): + # continue proprietary.append(root) subroutines = [] From 28e501e17ace3d340c52ffcf7863da56dbc6674b Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Sun, 19 Dec 2021 04:11:24 -0600 Subject: [PATCH 067/148] update readme --- README.adoc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.adoc b/README.adoc index ddf4a9b..11fa68c 100644 --- a/README.adoc +++ b/README.adoc @@ -45,6 +45,17 @@ Whatever you do, do not insert proprietary `Copyright (C) RivieraWaves` code in RivieraWaves code is known to be easily available on GitHub with simple searches, but avoid looking at it, unless you wish to forfeit your right to directly contribute code here. ==== +== BL602 wifi +I'm working on the reverse engineering of the bl602 wifi. + +The source code is located in `src/` instead of `components/**`. + +Using `cmake` to build the wifi module and it will automatically add other components +from the original `libbl602_wifi.a` and create a new one. + +This should generate a usable `libbl602_wifi.a` to link against other bl602 components. +But, I'm still working on this and it hasn't been tested yet. + == Resources * https://github.com/pine64/bl602-docs[Pine64 SDK fork's documentation], if you figure something out that's documentation-worthy, please update that documentation. From c5250a09d0bf9d1d0c17f898c55bb82632ae0802 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Tue, 21 Dec 2021 02:26:46 -0600 Subject: [PATCH 068/148] fix dup symbols --- src/bl602_wifi/driver/phy/phy_rf/phy_bl602.c | 2 ++ src/include/bl602_wifi/phy_rf/phy_bl602.h | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bl602_wifi/driver/phy/phy_rf/phy_bl602.c b/src/bl602_wifi/driver/phy/phy_rf/phy_bl602.c index 8d4173e..6a2b927 100644 --- a/src/bl602_wifi/driver/phy/phy_rf/phy_bl602.c +++ b/src/bl602_wifi/driver/phy/phy_rf/phy_bl602.c @@ -18,6 +18,8 @@ static int8_t rxgain_offset_vs_temperature; // :79:15 static int8_t poweroffset[14]; // :80:15 +struct phy_env_tag phy_env[1]; // :75:20 + void phy_config_rxgain(int offset) { if (rxgain_offset_vs_temperature != offset) { rxgain_offset_vs_temperature = (int8_t) offset; diff --git a/src/include/bl602_wifi/phy_rf/phy_bl602.h b/src/include/bl602_wifi/phy_rf/phy_bl602.h index d74e62a..8f31b41 100644 --- a/src/include/bl602_wifi/phy_rf/phy_bl602.h +++ b/src/include/bl602_wifi/phy_rf/phy_bl602.h @@ -31,7 +31,6 @@ struct phy_env_tag { uint8_t band; uint8_t chnl_type; }; // :54:8 -struct phy_env_tag phy_env[1]; // :75:20 void phy_config_rxgain(int offset); uint8_t phy_get_mac_freq(); From d0fa9a1aea9d07ecc88e6d9e51eb62b5290f2982 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Tue, 21 Dec 2021 02:26:54 -0600 Subject: [PATCH 069/148] add rf_dump_status --- src/bl602_wifi/driver/phy/phy_rf/rf.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/bl602_wifi/driver/phy/phy_rf/rf.c b/src/bl602_wifi/driver/phy/phy_rf/rf.c index cc2d079..3ef069f 100644 --- a/src/bl602_wifi/driver/phy/phy_rf/rf.c +++ b/src/bl602_wifi/driver/phy/phy_rf/rf.c @@ -18,3 +18,7 @@ void rf_init(void) { void rf_lo_isr(void) { return ; } + +void rf_dump_status(void) { + return ; +} \ No newline at end of file From 5b994a03ed104ed9244d1c415e0ee85144b2350a Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 22 Dec 2021 19:03:33 -0600 Subject: [PATCH 070/148] fix volatile attr in the pointer --- script/reglib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/reglib.py b/script/reglib.py index 7db82d2..ff0aeee 100755 --- a/script/reglib.py +++ b/script/reglib.py @@ -226,7 +226,7 @@ def genHeader(self): '\t};', "}" + f' {self.name}_regs;', f'#define {self.name.upper()}_BASE {hex(self.base)}', - f'#define {self.name.upper()} (({self.name}_regs* volatile)({self.name.upper()}_BASE))' + f'#define {self.name.upper()} ((volatile {self.name}_regs*)({self.name.upper()}_BASE))' ]) return s From d9ccd5d4312be1e7ec68781d832aa82897364ef2 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 22 Dec 2021 19:09:41 -0600 Subject: [PATCH 071/148] modify retry logic --- src/bl602_wifi/driver/phy/phy_rf/bl602_rf_private.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/bl602_wifi/driver/phy/phy_rf/bl602_rf_private.c b/src/bl602_wifi/driver/phy/phy_rf/bl602_rf_private.c index 1d42423..eb71747 100644 --- a/src/bl602_wifi/driver/phy/phy_rf/bl602_rf_private.c +++ b/src/bl602_wifi/driver/phy/phy_rf/bl602_rf_private.c @@ -188,10 +188,11 @@ void rf_pri_fcal(void) { uint16_t cw = 0x80; while (1) { for (int j = 6; j >= 0; j--) { - if (rf_pri_fcal_meas(cw) < c0) { + int cnt = rf_pri_fcal_meas(cw); + if (cnt < c0) { cw -= (1 << j); } else { - if (rf_pri_fcal_meas(cw) > c1) { + if (cnt > c1) { cw += (1 << j); } else break; } @@ -201,7 +202,7 @@ void rf_pri_fcal(void) { break; printf("Unexpected cw %ld\r\n", cw); - + cw = 0x80; /// reset RF->sdm1.lo_sdm_rstb = 0; RF->fbdv.lo_fbdv_rst = 1; @@ -210,10 +211,8 @@ void rf_pri_fcal(void) { RF->fbdv.lo_fbdv_rst = 0; BL602_Delay_US(0x32); } - cw++; channel_cnt_opt_table[0] = rf_pri_fcal_meas(cw); - for (int i = 1; i < 40; i++) { uint16_t cnt = rf_pri_fcal_meas(cw-i); channel_cnt_opt_table[i] = cnt; @@ -222,7 +221,7 @@ void rf_pri_fcal(void) { for (int i = 0, j = 0; i < 21; i++) { while (channel_cnt_opt_table[j] < channel_cnt_table[i]) j++; - channel_cw_table[i] = cw - (j - 1); /// hmmm what if j = 0?\ + channel_cw_table[i] = cw - (j - 1); /// hmmm what if j = 0? /// or it can't because cw was + 1.. if (j > 0) j--; } @@ -268,6 +267,7 @@ void rf_pri_start_txdfe() { static void rf_pri_config_channel(uint32_t channel_index) { // sdm = sigma-delta modulator ? + printf("lo_vco_freq[%d] = %d, %d\n", channel_index, rf_calib_data->lo[channel_index].fcal, rf_calib_data->lo[channel_index].acal); PACK(RF->vco1, vco1) { vco1.lo_vco_freq_cw = rf_calib_data->lo[channel_index].fcal; vco1.lo_vco_idac_cw = rf_calib_data->lo[channel_index].acal; From 65ad9699dce6e9f8b2427b8331971efb924de64a Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 22 Dec 2021 19:10:47 -0600 Subject: [PATCH 072/148] change volatile order in the type --- src/include/phy/agc.h | 2 +- src/include/phy/agcram.h | 2 +- src/include/phy/bz_phy.h | 2 +- src/include/phy/bz_phy_agc.h | 2 +- src/include/phy/dma.h | 2 +- src/include/phy/ipc.h | 2 +- src/include/phy/mac_core.h | 2 +- src/include/phy/mac_pl.h | 2 +- src/include/phy/mdm.h | 2 +- src/include/phy/sysctrl.h | 2 +- src/include/phy/sysctrl92.h | 2 +- src/include/soc/AON.h | 2 +- src/include/soc/HBN.h | 2 +- src/include/soc/cci.h | 2 +- src/include/soc/cks.h | 2 +- src/include/soc/dma.h | 2 +- src/include/soc/ef_ctrl.h | 2 +- src/include/soc/ef_data_0.h | 2 +- src/include/soc/ef_data_1.h | 2 +- src/include/soc/glb.h | 2 +- src/include/soc/gpip.h | 2 +- src/include/soc/i2c.h | 2 +- src/include/soc/ir.h | 2 +- src/include/soc/l1c.h | 2 +- src/include/soc/pds.h | 2 +- src/include/soc/pwm.h | 2 +- src/include/soc/rf.h | 2 +- src/include/soc/sec_dbg.h | 2 +- src/include/soc/sec_eng.h | 2 +- src/include/soc/sf_ctrl.h | 2 +- src/include/soc/spi.h | 2 +- src/include/soc/timer.h | 2 +- src/include/soc/tzc_nsec.h | 2 +- src/include/soc/tzc_sec.h | 2 +- src/include/soc/uart.h | 2 +- 35 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/include/phy/agc.h b/src/include/phy/agc.h index a58e169..1fd0198 100644 --- a/src/include/phy/agc.h +++ b/src/include/phy/agc.h @@ -428,4 +428,4 @@ typedef union { }; } agc_regs; #define AGC_BASE 0x44c0b000 -#define AGC ((agc_regs* volatile)(AGC_BASE)) \ No newline at end of file +#define AGC ((volatile agc_regs*)(AGC_BASE)) \ No newline at end of file diff --git a/src/include/phy/agcram.h b/src/include/phy/agcram.h index e32c3c9..284b96a 100644 --- a/src/include/phy/agcram.h +++ b/src/include/phy/agcram.h @@ -6,4 +6,4 @@ typedef union { }; } agcram_regs; #define AGCRAM_BASE 0x54c0a000 -#define AGCRAM ((agcram_regs* volatile)(AGCRAM_BASE)) \ No newline at end of file +#define AGCRAM ((volatile agcram_regs*)(AGCRAM_BASE)) \ No newline at end of file diff --git a/src/include/phy/bz_phy.h b/src/include/phy/bz_phy.h index 4e30a52..f28b8b7 100644 --- a/src/include/phy/bz_phy.h +++ b/src/include/phy/bz_phy.h @@ -883,4 +883,4 @@ typedef union { }; } bz_phy_regs; #define BZ_PHY_BASE 0x40002800 -#define BZ_PHY ((bz_phy_regs* volatile)(BZ_PHY_BASE)) \ No newline at end of file +#define BZ_PHY ((volatile bz_phy_regs*)(BZ_PHY_BASE)) \ No newline at end of file diff --git a/src/include/phy/bz_phy_agc.h b/src/include/phy/bz_phy_agc.h index ee4702f..6a41883 100644 --- a/src/include/phy/bz_phy_agc.h +++ b/src/include/phy/bz_phy_agc.h @@ -583,4 +583,4 @@ typedef union { }; } bz_phy_agc_regs; #define BZ_PHY_AGC_BASE 0x40002c00 -#define BZ_PHY_AGC ((bz_phy_agc_regs* volatile)(BZ_PHY_AGC_BASE)) \ No newline at end of file +#define BZ_PHY_AGC ((volatile bz_phy_agc_regs*)(BZ_PHY_AGC_BASE)) \ No newline at end of file diff --git a/src/include/phy/dma.h b/src/include/phy/dma.h index 9c4e2fd..0cd255b 100644 --- a/src/include/phy/dma.h +++ b/src/include/phy/dma.h @@ -88,4 +88,4 @@ typedef union { }; } dma_regs; #define DMA_BASE 0x44a00000 -#define DMA ((dma_regs* volatile)(DMA_BASE)) \ No newline at end of file +#define DMA ((volatile dma_regs*)(DMA_BASE)) \ No newline at end of file diff --git a/src/include/phy/ipc.h b/src/include/phy/ipc.h index c20a865..176b7bd 100644 --- a/src/include/phy/ipc.h +++ b/src/include/phy/ipc.h @@ -49,4 +49,4 @@ typedef union { }; } ipc_regs; #define IPC_BASE 0x44800000 -#define IPC ((ipc_regs* volatile)(IPC_BASE)) \ No newline at end of file +#define IPC ((volatile ipc_regs*)(IPC_BASE)) \ No newline at end of file diff --git a/src/include/phy/mac_core.h b/src/include/phy/mac_core.h index f869d75..50ed2e6 100644 --- a/src/include/phy/mac_core.h +++ b/src/include/phy/mac_core.h @@ -825,4 +825,4 @@ typedef union { }; } mac_core_regs; #define MAC_CORE_BASE 0x44b00000 -#define MAC_CORE ((mac_core_regs* volatile)(MAC_CORE_BASE)) \ No newline at end of file +#define MAC_CORE ((volatile mac_core_regs*)(MAC_CORE_BASE)) \ No newline at end of file diff --git a/src/include/phy/mac_pl.h b/src/include/phy/mac_pl.h index 918266a..742907f 100644 --- a/src/include/phy/mac_pl.h +++ b/src/include/phy/mac_pl.h @@ -867,4 +867,4 @@ typedef union { }; } mac_pl_regs; #define MAC_PL_BASE 0x44b08000 -#define MAC_PL ((mac_pl_regs* volatile)(MAC_PL_BASE)) \ No newline at end of file +#define MAC_PL ((volatile mac_pl_regs*)(MAC_PL_BASE)) \ No newline at end of file diff --git a/src/include/phy/mdm.h b/src/include/phy/mdm.h index 1ab9362..ee0f605 100644 --- a/src/include/phy/mdm.h +++ b/src/include/phy/mdm.h @@ -162,4 +162,4 @@ typedef union { }; } mdm_regs; #define MDM_BASE 0x44c00000 -#define MDM ((mdm_regs* volatile)(MDM_BASE)) \ No newline at end of file +#define MDM ((volatile mdm_regs*)(MDM_BASE)) \ No newline at end of file diff --git a/src/include/phy/sysctrl.h b/src/include/phy/sysctrl.h index 8f186ab..63db1a6 100644 --- a/src/include/phy/sysctrl.h +++ b/src/include/phy/sysctrl.h @@ -32,4 +32,4 @@ typedef union { }; } sysctrl_regs; #define SYSCTRL_BASE 0x44900000 -#define SYSCTRL ((sysctrl_regs* volatile)(SYSCTRL_BASE)) \ No newline at end of file +#define SYSCTRL ((volatile sysctrl_regs*)(SYSCTRL_BASE)) \ No newline at end of file diff --git a/src/include/phy/sysctrl92.h b/src/include/phy/sysctrl92.h index a137b6b..00c7961 100644 --- a/src/include/phy/sysctrl92.h +++ b/src/include/phy/sysctrl92.h @@ -7,4 +7,4 @@ typedef union { }; } sysctrl92_regs; #define SYSCTRL92_BASE 0x44920000 -#define SYSCTRL92 ((sysctrl92_regs* volatile)(SYSCTRL92_BASE)) \ No newline at end of file +#define SYSCTRL92 ((volatile sysctrl92_regs*)(SYSCTRL92_BASE)) \ No newline at end of file diff --git a/src/include/soc/AON.h b/src/include/soc/AON.h index 4089f3b..f3d842a 100644 --- a/src/include/soc/AON.h +++ b/src/include/soc/AON.h @@ -394,4 +394,4 @@ typedef union { }; } AON_regs; #define AON_BASE 0x4000f000 -#define AON ((AON_regs* volatile)(AON_BASE)) \ No newline at end of file +#define AON ((volatile AON_regs*)(AON_BASE)) \ No newline at end of file diff --git a/src/include/soc/HBN.h b/src/include/soc/HBN.h index 819f0e5..5b0fa88 100644 --- a/src/include/soc/HBN.h +++ b/src/include/soc/HBN.h @@ -206,4 +206,4 @@ typedef union { }; } HBN_regs; #define HBN_BASE 0x4000f000 -#define HBN ((HBN_regs* volatile)(HBN_BASE)) \ No newline at end of file +#define HBN ((volatile HBN_regs*)(HBN_BASE)) \ No newline at end of file diff --git a/src/include/soc/cci.h b/src/include/soc/cci.h index d9d4def..05448b0 100644 --- a/src/include/soc/cci.h +++ b/src/include/soc/cci.h @@ -47,4 +47,4 @@ typedef union { }; } cci_regs; #define CCI_BASE 0x40008000 -#define CCI ((cci_regs* volatile)(CCI_BASE)) \ No newline at end of file +#define CCI ((volatile cci_regs*)(CCI_BASE)) \ No newline at end of file diff --git a/src/include/soc/cks.h b/src/include/soc/cks.h index 474e844..8f58ea1 100644 --- a/src/include/soc/cks.h +++ b/src/include/soc/cks.h @@ -27,4 +27,4 @@ typedef union { }; } cks_regs; #define CKS_BASE 0x4000a000 -#define CKS ((cks_regs* volatile)(CKS_BASE)) \ No newline at end of file +#define CKS ((volatile cks_regs*)(CKS_BASE)) \ No newline at end of file diff --git a/src/include/soc/dma.h b/src/include/soc/dma.h index 8b88f88..d5cd609 100644 --- a/src/include/soc/dma.h +++ b/src/include/soc/dma.h @@ -301,4 +301,4 @@ typedef union { }; } dma_regs; #define DMA_BASE 0x4000c000 -#define DMA ((dma_regs* volatile)(DMA_BASE)) \ No newline at end of file +#define DMA ((volatile dma_regs*)(DMA_BASE)) \ No newline at end of file diff --git a/src/include/soc/ef_ctrl.h b/src/include/soc/ef_ctrl.h index b2ef074..c316c96 100644 --- a/src/include/soc/ef_ctrl.h +++ b/src/include/soc/ef_ctrl.h @@ -187,4 +187,4 @@ typedef union { }; } ef_ctrl_regs; #define EF_CTRL_BASE 0x40007000 -#define EF_CTRL ((ef_ctrl_regs* volatile)(EF_CTRL_BASE)) \ No newline at end of file +#define EF_CTRL ((volatile ef_ctrl_regs*)(EF_CTRL_BASE)) \ No newline at end of file diff --git a/src/include/soc/ef_data_0.h b/src/include/soc/ef_data_0.h index 612e008..6e4c15f 100644 --- a/src/include/soc/ef_data_0.h +++ b/src/include/soc/ef_data_0.h @@ -235,4 +235,4 @@ typedef union { }; } ef_data_0_regs; #define EF_DATA_0_BASE 0x40007000 -#define EF_DATA_0 ((ef_data_0_regs* volatile)(EF_DATA_0_BASE)) \ No newline at end of file +#define EF_DATA_0 ((volatile ef_data_0_regs*)(EF_DATA_0_BASE)) \ No newline at end of file diff --git a/src/include/soc/ef_data_1.h b/src/include/soc/ef_data_1.h index 3667e6a..41c0a6b 100644 --- a/src/include/soc/ef_data_1.h +++ b/src/include/soc/ef_data_1.h @@ -127,4 +127,4 @@ typedef union { }; } ef_data_1_regs; #define EF_DATA_1_BASE 0x40007000 -#define EF_DATA_1 ((ef_data_1_regs* volatile)(EF_DATA_1_BASE)) \ No newline at end of file +#define EF_DATA_1 ((volatile ef_data_1_regs*)(EF_DATA_1_BASE)) \ No newline at end of file diff --git a/src/include/soc/glb.h b/src/include/soc/glb.h index 6fb5e34..7a2a5f0 100644 --- a/src/include/soc/glb.h +++ b/src/include/soc/glb.h @@ -965,4 +965,4 @@ typedef union { }; } glb_regs; #define GLB_BASE 0x40000000 -#define GLB ((glb_regs* volatile)(GLB_BASE)) \ No newline at end of file +#define GLB ((volatile glb_regs*)(GLB_BASE)) \ No newline at end of file diff --git a/src/include/soc/gpip.h b/src/include/soc/gpip.h index ae4f5a4..8e173bd 100644 --- a/src/include/soc/gpip.h +++ b/src/include/soc/gpip.h @@ -79,4 +79,4 @@ typedef union { }; } gpip_regs; #define GPIP_BASE 0x40002000 -#define GPIP ((gpip_regs* volatile)(GPIP_BASE)) \ No newline at end of file +#define GPIP ((volatile gpip_regs*)(GPIP_BASE)) \ No newline at end of file diff --git a/src/include/soc/i2c.h b/src/include/soc/i2c.h index 805c66b..241f783 100644 --- a/src/include/soc/i2c.h +++ b/src/include/soc/i2c.h @@ -139,4 +139,4 @@ typedef union { }; } i2c_regs; #define I2C_BASE 0x4000a300 -#define I2C ((i2c_regs* volatile)(I2C_BASE)) \ No newline at end of file +#define I2C ((volatile i2c_regs*)(I2C_BASE)) \ No newline at end of file diff --git a/src/include/soc/ir.h b/src/include/soc/ir.h index c1b3a7f..283c73f 100644 --- a/src/include/soc/ir.h +++ b/src/include/soc/ir.h @@ -192,4 +192,4 @@ typedef union { }; } ir_regs; #define IR_BASE 0x4000a600 -#define IR ((ir_regs* volatile)(IR_BASE)) \ No newline at end of file +#define IR ((volatile ir_regs*)(IR_BASE)) \ No newline at end of file diff --git a/src/include/soc/l1c.h b/src/include/soc/l1c.h index ce77cad..694143d 100644 --- a/src/include/soc/l1c.h +++ b/src/include/soc/l1c.h @@ -81,4 +81,4 @@ typedef union { }; } l1c_regs; #define L1C_BASE 0x40009000 -#define L1C ((l1c_regs* volatile)(L1C_BASE)) \ No newline at end of file +#define L1C ((volatile l1c_regs*)(L1C_BASE)) \ No newline at end of file diff --git a/src/include/soc/pds.h b/src/include/soc/pds.h index c0e6079..8b726ce 100644 --- a/src/include/soc/pds.h +++ b/src/include/soc/pds.h @@ -281,4 +281,4 @@ typedef union { }; } pds_regs; #define PDS_BASE 0x4000e000 -#define PDS ((pds_regs* volatile)(PDS_BASE)) \ No newline at end of file +#define PDS ((volatile pds_regs*)(PDS_BASE)) \ No newline at end of file diff --git a/src/include/soc/pwm.h b/src/include/soc/pwm.h index 14c358d..a2f94b8 100644 --- a/src/include/soc/pwm.h +++ b/src/include/soc/pwm.h @@ -264,4 +264,4 @@ typedef union { }; } pwm_regs; #define PWM_BASE 0x4000a400 -#define PWM ((pwm_regs* volatile)(PWM_BASE)) \ No newline at end of file +#define PWM ((volatile pwm_regs*)(PWM_BASE)) \ No newline at end of file diff --git a/src/include/soc/rf.h b/src/include/soc/rf.h index ee0c812..ac308cb 100644 --- a/src/include/soc/rf.h +++ b/src/include/soc/rf.h @@ -1931,4 +1931,4 @@ typedef union { }; } rf_regs; #define RF_BASE 0x40001000 -#define RF ((rf_regs* volatile)(RF_BASE)) \ No newline at end of file +#define RF ((volatile rf_regs*)(RF_BASE)) \ No newline at end of file diff --git a/src/include/soc/sec_dbg.h b/src/include/soc/sec_dbg.h index 8687274..b87c44c 100644 --- a/src/include/soc/sec_dbg.h +++ b/src/include/soc/sec_dbg.h @@ -59,4 +59,4 @@ typedef union { }; } sec_dbg_regs; #define SEC_DBG_BASE 0x40003000 -#define SEC_DBG ((sec_dbg_regs* volatile)(SEC_DBG_BASE)) \ No newline at end of file +#define SEC_DBG ((volatile sec_dbg_regs*)(SEC_DBG_BASE)) \ No newline at end of file diff --git a/src/include/soc/sec_eng.h b/src/include/soc/sec_eng.h index be41930..714ceed 100644 --- a/src/include/soc/sec_eng.h +++ b/src/include/soc/sec_eng.h @@ -621,4 +621,4 @@ typedef union { }; } sec_eng_regs; #define SEC_ENG_BASE 0x40004000 -#define SEC_ENG ((sec_eng_regs* volatile)(SEC_ENG_BASE)) \ No newline at end of file +#define SEC_ENG ((volatile sec_eng_regs*)(SEC_ENG_BASE)) \ No newline at end of file diff --git a/src/include/soc/sf_ctrl.h b/src/include/soc/sf_ctrl.h index 5eaec5c..d35397c 100644 --- a/src/include/soc/sf_ctrl.h +++ b/src/include/soc/sf_ctrl.h @@ -664,4 +664,4 @@ typedef union { }; } sf_ctrl_regs; #define SF_CTRL_BASE 0x4000b000 -#define SF_CTRL ((sf_ctrl_regs* volatile)(SF_CTRL_BASE)) \ No newline at end of file +#define SF_CTRL ((volatile sf_ctrl_regs*)(SF_CTRL_BASE)) \ No newline at end of file diff --git a/src/include/soc/spi.h b/src/include/soc/spi.h index 77d6650..af70f94 100644 --- a/src/include/soc/spi.h +++ b/src/include/soc/spi.h @@ -136,4 +136,4 @@ typedef union { }; } spi_regs; #define SPI_BASE 0x4000a200 -#define SPI ((spi_regs* volatile)(SPI_BASE)) \ No newline at end of file +#define SPI ((volatile spi_regs*)(SPI_BASE)) \ No newline at end of file diff --git a/src/include/soc/timer.h b/src/include/soc/timer.h index bf6d225..88f74d9 100644 --- a/src/include/soc/timer.h +++ b/src/include/soc/timer.h @@ -281,4 +281,4 @@ typedef union { }; } timer_regs; #define TIMER_BASE 0x4000a500 -#define TIMER ((timer_regs* volatile)(TIMER_BASE)) \ No newline at end of file +#define TIMER ((volatile timer_regs*)(TIMER_BASE)) \ No newline at end of file diff --git a/src/include/soc/tzc_nsec.h b/src/include/soc/tzc_nsec.h index c82efc8..a7bd73c 100644 --- a/src/include/soc/tzc_nsec.h +++ b/src/include/soc/tzc_nsec.h @@ -59,4 +59,4 @@ typedef union { }; } tzc_nsec_regs; #define TZC_NSEC_BASE 0x40006000 -#define TZC_NSEC ((tzc_nsec_regs* volatile)(TZC_NSEC_BASE)) \ No newline at end of file +#define TZC_NSEC ((volatile tzc_nsec_regs*)(TZC_NSEC_BASE)) \ No newline at end of file diff --git a/src/include/soc/tzc_sec.h b/src/include/soc/tzc_sec.h index 90582e2..07e3e79 100644 --- a/src/include/soc/tzc_sec.h +++ b/src/include/soc/tzc_sec.h @@ -59,4 +59,4 @@ typedef union { }; } tzc_sec_regs; #define TZC_SEC_BASE 0x40005000 -#define TZC_SEC ((tzc_sec_regs* volatile)(TZC_SEC_BASE)) \ No newline at end of file +#define TZC_SEC ((volatile tzc_sec_regs*)(TZC_SEC_BASE)) \ No newline at end of file diff --git a/src/include/soc/uart.h b/src/include/soc/uart.h index c8d2e76..47c0ef9 100644 --- a/src/include/soc/uart.h +++ b/src/include/soc/uart.h @@ -189,4 +189,4 @@ typedef union { }; } uart_regs; #define UART_BASE 0x4000a000 -#define UART ((uart_regs* volatile)(UART_BASE)) \ No newline at end of file +#define UART ((volatile uart_regs*)(UART_BASE)) \ No newline at end of file From 9803c2081adfb640eda10cd18d8f937a4f6d286f Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Wed, 22 Dec 2021 19:11:03 -0600 Subject: [PATCH 073/148] add some ignores --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 5e4a051..66dc929 100644 --- a/.gitignore +++ b/.gitignore @@ -305,4 +305,6 @@ tags [._]*.un~ # End of https://www.toptal.com/developers/gitignore/api/emacs,vim,pycharm+all,python -/build +/build* +.vscode/ +*.cache \ No newline at end of file From d65e629086ff1c7f0697a9e53a49281d0746f859 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Thu, 23 Dec 2021 05:20:19 -0600 Subject: [PATCH 074/148] move macro to global --- src/{bl602_wifi/driver/phy/phy_rf => include}/macro.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/{bl602_wifi/driver/phy/phy_rf => include}/macro.h (94%) diff --git a/src/bl602_wifi/driver/phy/phy_rf/macro.h b/src/include/macro.h similarity index 94% rename from src/bl602_wifi/driver/phy/phy_rf/macro.h rename to src/include/macro.h index 2b706f6..6857eff 100644 --- a/src/bl602_wifi/driver/phy/phy_rf/macro.h +++ b/src/include/macro.h @@ -43,5 +43,5 @@ #define _APPLY_NEXT() APPLY_NEXT #define PACK(var, name) for (int tip = 1; tip;) for (__typeof__ (var) name = var; tip; tip = 0, var = name) - +#define STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[(COND)?1:-1] #endif \ No newline at end of file From 05d666f2c93fed3381465523725d7fd23c77dcb3 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Thu, 23 Dec 2021 05:20:30 -0600 Subject: [PATCH 075/148] adding sysctrl and ipc --- src/bl602_wifi/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bl602_wifi/CMakeLists.txt b/src/bl602_wifi/CMakeLists.txt index 2dbb21e..941d82f 100644 --- a/src/bl602_wifi/CMakeLists.txt +++ b/src/bl602_wifi/CMakeLists.txt @@ -1,4 +1,6 @@ init_bl602module("bl602_wifi") add_bl602module("driver/phy/phy_rf") add_bl602module("driver/phyif") +add_bl602module("driver/sysctrl") +add_bl602module("driver/ipc") end_bl602module() \ No newline at end of file From becea0d54ab821453438864f4c255b83e476cb98 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Thu, 23 Dec 2021 05:20:50 -0600 Subject: [PATCH 076/148] update IPC regs --- script/manualext.py | 21 +++- src/include/phy/ipc.h | 89 ++++++++------ src/svd/ipc.svd | 272 ++++++++++++++++++++++++++++++++++-------- 3 files changed, 294 insertions(+), 88 deletions(-) diff --git a/script/manualext.py b/script/manualext.py index 601467a..56cff04 100755 --- a/script/manualext.py +++ b/script/manualext.py @@ -432,7 +432,26 @@ def getregs(fname, pattern='name'): peris['ipc'] = Peripheral(peripheral('ipc', 0x44800000, 0x1000)) for code, offset in getregs("../components/bl602/bl602_wifidrv/bl60x_wifi_driver/reg_ipc_app.h", pattern='brief'): - RegFromComment(offset + 0x44800000, code) + RegFromComment(offset + 0x44800000, code.lower()) +Reg('emb2app_line_sel_low', 0x44800000 + 0x14) +for i in range(0,16): + FieldBit(f'emb2app{i}_sel', i*2, 2) +Reg('emb2app_line_sel_high', 0x44800000 + 0x18) +ipc_names = [] +def flipname(name): + name = name.replace('app', 'XXXXX') + name = name.replace('emb', 'YYYYY') + name = name.replace('XXXXX', 'emb') + name = name.replace('YYYYY', 'app') + return name +for reg in peris['ipc'].regs: + if (len(reg.fields) == 1): + reg.fields = [] + ipc_names.append((flipname(reg.name), reg.offset + 0x100, reg.fields)) +for name, offset, f in ipc_names: + Reg(name, offset + 0x44800000) + for i in f: + FieldBit(flipname(i.name), i.lsb, i.len) #open('../src/include/phy/ipc.h', 'w').write('\n'.join(GenHeader())) #print('\n'.join(GenHeader())) diff --git a/src/include/phy/ipc.h b/src/include/phy/ipc.h index 176b7bd..46b20d1 100644 --- a/src/include/phy/ipc.h +++ b/src/include/phy/ipc.h @@ -2,50 +2,67 @@ typedef union { uint32_t regs[0x400]; uint8_t pad[0x1000]; struct { + uint32_t app2emb_trigger; // @ 0x0 + uint32_t emb2app_rawstatus; // @ 0x4 + uint32_t emb2app_ack; // @ 0x8 + uint32_t emb2app_unmask_set; // @ 0xc + uint32_t emb2app_unmask_clear; // @ 0x10 union { uint32_t value; struct { - uint32_t APP2EMB_TRIGGER : 32; // @ 31 -- 0 # 0x0 + uint32_t emb2app0_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t emb2app1_sel : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t emb2app2_sel : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t emb2app3_sel : 2; // @ 7 -- 6 # 0xffffff3f + uint32_t emb2app4_sel : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t emb2app5_sel : 2; // @ 11 -- 10 # 0xfffff3ff + uint32_t emb2app6_sel : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t emb2app7_sel : 2; // @ 15 -- 14 # 0xffff3fff + uint32_t emb2app8_sel : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t emb2app9_sel : 2; // @ 19 -- 18 # 0xfff3ffff + uint32_t emb2app10_sel : 2; // @ 21 -- 20 # 0xffcfffff + uint32_t emb2app11_sel : 2; // @ 23 -- 22 # 0xff3fffff + uint32_t emb2app12_sel : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t emb2app13_sel : 2; // @ 27 -- 26 # 0xf3ffffff + uint32_t emb2app14_sel : 2; // @ 29 -- 28 # 0xcfffffff + uint32_t emb2app15_sel : 2; // @ 31 -- 30 # 0x3fffffff }; - } APP2EMB_TRIGGER; // @ 0x0 + } emb2app_line_sel_low; // @ 0x14 + uint32_t emb2app_line_sel_high; // @ 0x18 + uint32_t emb2app_status; // @ 0x1c + uint8_t pad0[0x20]; + uint32_t app_signature; // @ 0x40 + uint8_t pad1[0xbc]; + uint32_t emb2app_trigger; // @ 0x100 + uint32_t app2emb_rawstatus; // @ 0x104 + uint32_t app2emb_ack; // @ 0x108 + uint32_t app2emb_unmask_set; // @ 0x10c + uint32_t app2emb_unmask_clear; // @ 0x110 union { uint32_t value; struct { - uint32_t EMB2APP_RAWSTATUS : 32; // @ 31 -- 0 # 0x0 + uint32_t app2emb0_sel : 2; // @ 1 -- 0 # 0xfffffffc + uint32_t app2emb1_sel : 2; // @ 3 -- 2 # 0xfffffff3 + uint32_t app2emb2_sel : 2; // @ 5 -- 4 # 0xffffffcf + uint32_t app2emb3_sel : 2; // @ 7 -- 6 # 0xffffff3f + uint32_t app2emb4_sel : 2; // @ 9 -- 8 # 0xfffffcff + uint32_t app2emb5_sel : 2; // @ 11 -- 10 # 0xfffff3ff + uint32_t app2emb6_sel : 2; // @ 13 -- 12 # 0xffffcfff + uint32_t app2emb7_sel : 2; // @ 15 -- 14 # 0xffff3fff + uint32_t app2emb8_sel : 2; // @ 17 -- 16 # 0xfffcffff + uint32_t app2emb9_sel : 2; // @ 19 -- 18 # 0xfff3ffff + uint32_t app2emb10_sel : 2; // @ 21 -- 20 # 0xffcfffff + uint32_t app2emb11_sel : 2; // @ 23 -- 22 # 0xff3fffff + uint32_t app2emb12_sel : 2; // @ 25 -- 24 # 0xfcffffff + uint32_t app2emb13_sel : 2; // @ 27 -- 26 # 0xf3ffffff + uint32_t app2emb14_sel : 2; // @ 29 -- 28 # 0xcfffffff + uint32_t app2emb15_sel : 2; // @ 31 -- 30 # 0x3fffffff }; - } EMB2APP_RAWSTATUS; // @ 0x4 - union { - uint32_t value; - struct { - uint32_t EMB2APP_ACK : 32; // @ 31 -- 0 # 0x0 - }; - } EMB2APP_ACK; // @ 0x8 - union { - uint32_t value; - struct { - uint32_t EMB2APP_UNMASK : 32; // @ 31 -- 0 # 0x0 - }; - } EMB2APP_UNMASK_SET; // @ 0xc - union { - uint32_t value; - struct { - uint32_t EMB2APP_UNMASK : 32; // @ 31 -- 0 # 0x0 - }; - } EMB2APP_UNMASK_CLEAR; // @ 0x10 - uint8_t pad0[0x8]; - union { - uint32_t value; - struct { - uint32_t EMB2APP_STATUS : 32; // @ 31 -- 0 # 0x0 - }; - } EMB2APP_STATUS; // @ 0x1c - uint8_t pad1[0x20]; - union { - uint32_t value; - struct { - uint32_t APP_SIGNATURE : 32; // @ 31 -- 0 # 0x0 - }; - } APP_SIGNATURE; // @ 0x40 + } app2emb_line_sel_low; // @ 0x114 + uint32_t app2emb_line_sel_high; // @ 0x118 + uint32_t app2emb_status; // @ 0x11c + uint8_t pad2[0x20]; + uint32_t emb_signature; // @ 0x140 }; } ipc_regs; #define IPC_BASE 0x44800000 diff --git a/src/svd/ipc.svd b/src/svd/ipc.svd index 011f109..75bc770 100644 --- a/src/svd/ipc.svd +++ b/src/svd/ipc.svd @@ -12,88 +12,258 @@ - APP2EMB_TRIGGER - APP2EMB_TRIGGER. + app2emb_trigger + app2emb_trigger. 0x0 - - - APP2EMB_TRIGGER - 31 - 0 - - - EMB2APP_RAWSTATUS - EMB2APP_RAWSTATUS. + emb2app_rawstatus + emb2app_rawstatus. 0x4 - - - EMB2APP_RAWSTATUS - 31 - 0 - - - EMB2APP_ACK - EMB2APP_ACK. + emb2app_ack + emb2app_ack. 0x8 - - - EMB2APP_ACK - 31 - 0 - - - EMB2APP_UNMASK_SET - EMB2APP_UNMASK_SET. + emb2app_unmask_set + emb2app_unmask_set. 0xc - - - EMB2APP_UNMASK - 31 - 0 - - - EMB2APP_UNMASK_CLEAR - EMB2APP_UNMASK_CLEAR. + emb2app_unmask_clear + emb2app_unmask_clear. 0x10 + + + emb2app_line_sel_low + emb2app_line_sel_low. + 0x14 - EMB2APP_UNMASK + emb2app15_sel 31 + 30 + + + emb2app14_sel + 29 + 28 + + + emb2app13_sel + 27 + 26 + + + emb2app12_sel + 25 + 24 + + + emb2app11_sel + 23 + 22 + + + emb2app10_sel + 21 + 20 + + + emb2app9_sel + 19 + 18 + + + emb2app8_sel + 17 + 16 + + + emb2app7_sel + 15 + 14 + + + emb2app6_sel + 13 + 12 + + + emb2app5_sel + 11 + 10 + + + emb2app4_sel + 9 + 8 + + + emb2app3_sel + 7 + 6 + + + emb2app2_sel + 5 + 4 + + + emb2app1_sel + 3 + 2 + + + emb2app0_sel + 1 0 - EMB2APP_STATUS - EMB2APP_STATUS. + emb2app_line_sel_high + emb2app_line_sel_high. + 0x18 + + + emb2app_status + emb2app_status. 0x1c - - - EMB2APP_STATUS - 31 - 0 - - - APP_SIGNATURE - APP_SIGNATURE. + app_signature + app_signature. 0x40 + + + emb2app_trigger + emb2app_trigger. + 0x100 + + + app2emb_rawstatus + app2emb_rawstatus. + 0x104 + + + app2emb_ack + app2emb_ack. + 0x108 + + + app2emb_unmask_set + app2emb_unmask_set. + 0x10c + + + app2emb_unmask_clear + app2emb_unmask_clear. + 0x110 + + + app2emb_line_sel_low + app2emb_line_sel_low. + 0x114 - APP_SIGNATURE + app2emb15_sel 31 + 30 + + + app2emb14_sel + 29 + 28 + + + app2emb13_sel + 27 + 26 + + + app2emb12_sel + 25 + 24 + + + app2emb11_sel + 23 + 22 + + + app2emb10_sel + 21 + 20 + + + app2emb9_sel + 19 + 18 + + + app2emb8_sel + 17 + 16 + + + app2emb7_sel + 15 + 14 + + + app2emb6_sel + 13 + 12 + + + app2emb5_sel + 11 + 10 + + + app2emb4_sel + 9 + 8 + + + app2emb3_sel + 7 + 6 + + + app2emb2_sel + 5 + 4 + + + app2emb1_sel + 3 + 2 + + + app2emb0_sel + 1 0 + + app2emb_line_sel_high + app2emb_line_sel_high. + 0x118 + + + app2emb_status + app2emb_status. + 0x11c + + + emb_signature + emb_signature. + 0x140 + \ No newline at end of file From 1845f40d036456f2c14b4fc521f0fa991c74934c Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Thu, 23 Dec 2021 05:21:09 -0600 Subject: [PATCH 077/148] use new macro --- src/bl602_wifi/driver/phy/phy_rf/bl602_rf_private.c | 2 +- src/bl602_wifi/driver/phy/phy_rf/phy_bl602.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bl602_wifi/driver/phy/phy_rf/bl602_rf_private.c b/src/bl602_wifi/driver/phy/phy_rf/bl602_rf_private.c index eb71747..381def7 100644 --- a/src/bl602_wifi/driver/phy/phy_rf/bl602_rf_private.c +++ b/src/bl602_wifi/driver/phy/phy_rf/bl602_rf_private.c @@ -80,7 +80,7 @@ static void rf_pri_restore_state_for_cal() { #include "rf_private_save.h" } -#include "macro.h" +#include #define mapper0(x) new_pucr1.x = 0; #define mapper1(x) new_pucr1.x = 1; #define P_CLR(...) APPLY(mapper0, __VA_ARGS__) diff --git a/src/bl602_wifi/driver/phy/phy_rf/phy_bl602.c b/src/bl602_wifi/driver/phy/phy_rf/phy_bl602.c index 6a2b927..fc4b638 100644 --- a/src/bl602_wifi/driver/phy/phy_rf/phy_bl602.c +++ b/src/bl602_wifi/driver/phy/phy_rf/phy_bl602.c @@ -13,7 +13,7 @@ #include #include #include -#include "macro.h" +#include static int8_t rxgain_offset_vs_temperature; // :79:15 static int8_t poweroffset[14]; // :80:15 From 6537668c32049edf173a218e742b43f7d4e6b37b Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Thu, 23 Dec 2021 05:21:28 -0600 Subject: [PATCH 078/148] reduce warning --- src/include/utils.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/utils.h b/src/include/utils.h index 3cbf09b..1b3c62d 100644 --- a/src/include/utils.h +++ b/src/include/utils.h @@ -3,8 +3,8 @@ #define MIN(x,y) (((x) > (y)) ? (y) : (x)) #define MAX(x,y) (((x) < (y)) ? (y) : (x)) int puts(char *s); -int printf(char *fmt,...); -void* memset(void *, int, long unsigned int); +int printf(const char *fmt,...); +void* memset(void *, int, unsigned int); void* memcpy(void*, const void*, unsigned int); void BL602_Delay_US(uint32_t cnt); void BL602_Delay_MS(uint32_t cnt); From db03980dd85106d5db098b126864fcfc1139c5a2 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Thu, 23 Dec 2021 05:21:39 -0600 Subject: [PATCH 079/148] sysctrl_init() --- src/bl602_wifi/driver/sysctrl/sysctrl.c | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/bl602_wifi/driver/sysctrl/sysctrl.c diff --git a/src/bl602_wifi/driver/sysctrl/sysctrl.c b/src/bl602_wifi/driver/sysctrl/sysctrl.c new file mode 100644 index 0000000..9df88cd --- /dev/null +++ b/src/bl602_wifi/driver/sysctrl/sysctrl.c @@ -0,0 +1,6 @@ +#include +#include +void sysctrl_init() { + SYSCTRL->diag_conf.value = 0x8000000c; + SYSCTRL->misc_cntl.set1 = 0x1ff; +} From 0231b45681d00deb067fc9edcb0a19fc72795d79 Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Thu, 23 Dec 2021 05:22:24 -0600 Subject: [PATCH 080/148] ipc and related headers --- src/bl602_wifi/driver/ipc/ipc_emb.c | 204 ++++++++++++++++++ src/bl602_wifi/driver/ipc/ipc_shared.c | 3 + src/include/bl602_wifi/ipc/ipc_emb.h | 33 +++ src/include/bl602_wifi/ipc/ipc_shared.h | 19 ++ src/include/bl602_wifi/la/la_mem.h | 8 + src/include/bl602_wifi/lmac/tx/tx_swdesc.h | 71 ++++++ .../bl602_wifi/modules/common/co_list.h | 12 ++ src/include/bl602_wifi/modules/ke/ke_env.h | 21 ++ src/include/bl602_wifi/modules/ke/ke_event.h | 12 ++ src/include/bl602_wifi/modules/ke/ke_mem.h | 11 + src/include/bl602_wifi/modules/ke/ke_msg.h | 41 ++++ src/include/bl602_wifi/modules/ke/ke_task.h | 74 +++++++ src/include/bl602_wifi/modules/mac/mac.h | 99 +++++++++ src/include/bl602_wifi/umac/txu/txu_cntrl.h | 16 ++ 14 files changed, 624 insertions(+) create mode 100644 src/bl602_wifi/driver/ipc/ipc_emb.c create mode 100644 src/bl602_wifi/driver/ipc/ipc_shared.c create mode 100644 src/include/bl602_wifi/ipc/ipc_emb.h create mode 100644 src/include/bl602_wifi/ipc/ipc_shared.h create mode 100644 src/include/bl602_wifi/la/la_mem.h create mode 100644 src/include/bl602_wifi/lmac/tx/tx_swdesc.h create mode 100644 src/include/bl602_wifi/modules/common/co_list.h create mode 100644 src/include/bl602_wifi/modules/ke/ke_env.h create mode 100644 src/include/bl602_wifi/modules/ke/ke_event.h create mode 100644 src/include/bl602_wifi/modules/ke/ke_mem.h create mode 100644 src/include/bl602_wifi/modules/ke/ke_msg.h create mode 100644 src/include/bl602_wifi/modules/ke/ke_task.h create mode 100644 src/include/bl602_wifi/modules/mac/mac.h create mode 100644 src/include/bl602_wifi/umac/txu/txu_cntrl.h diff --git a/src/bl602_wifi/driver/ipc/ipc_emb.c b/src/bl602_wifi/driver/ipc/ipc_emb.c new file mode 100644 index 0000000..52a1288 --- /dev/null +++ b/src/bl602_wifi/driver/ipc/ipc_emb.c @@ -0,0 +1,204 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IPC_EMB_SIGNATURE_RESET 0x49504332 + +int internel_cal_size_tx_desc; // :59:5 +static TaskHandle_t xTaskToNotify; // :91:21 +uint32_t ipc_emb_counter; // :92:10 +const uint32_t ipc_emb_evt_bit[5] = {0x80, 0x100, 0x200, 0x400, 0x800}; +struct ipc_emb_env_tag ipc_emb_env; // :110:24 +const int nx_txdesc_cnt_msk[1] = {3}; // :113:11 + +void ipc_emb_msg_dma_int_handler(void) { + // empty function + return ; +} + +void ipc_emb_dbg_dma_int_handler(void) { + DMA->int_ack.b7 = 1; + IPC->emb2app_trigger = 1; +} + +void ipc_emb_dump(void) { + // empty function + return ; +} + +bool ipc_emb_tx_q_has_data(int queue_idx) { + // guessed, not sure if it's !=0 or == 0 + // rationally, it should be != 0 + return (ipc_emb_env.txdesc + (ipc_emb_env.txdesc_idx & 3))->ready != 0; +} + +uint32_t ipc_emb_tx_evt_field(uint32_t stat) { + // can't find impl + return 0; +} + +void ipc_emb_txcfm_ind(uint32_t queue_bits) { + IPC->emb2app_trigger = queue_bits << 7; +} + +void ipc_emb_init(void) { + xTaskToNotify = xTaskGetCurrentTaskHandle(); + memset(&ipc_emb_env, 0, 0x20); + ipc_emb_env.txdesc = ipc_shared_env.txdesc0; + ASSERT_ERR(IPC->emb_signature == IPC_EMB_SIGNATURE_RESET); + IPC->app2emb_line_sel_low.value = 0; + IPC->app2emb_line_sel_high = 0; + IPC->app2emb_line_sel_low.app2emb0_sel = 0; + IPC->app2emb_line_sel_low.app2emb1_sel = 1; + IPC->app2emb_line_sel_low.app2emb4_sel = 2; + IPC->app2emb_line_sel_low.app2emb5_sel = 2; + IPC->app2emb_line_sel_low.app2emb6_sel = 2; + IPC->app2emb_line_sel_low.app2emb8_sel = 3; + IPC->app2emb_line_sel_low.app2emb9_sel = 3; + IPC->app2emb_line_sel_low.app2emb10_sel = 3; + IPC->app2emb_line_sel_low.app2emb11_sel = 3; + IPC->app2emb_line_sel_low.app2emb12_sel = 3; + IPC->app2emb_unmask_set = 0x1f03; +} + +void ipc_emb_notify(void) { + ASSERT_ERR(xTaskToNotify != NULL); + if (TrapNetCounter == 0) { + xTaskGenericNotify(xTaskToNotify,0,eIncrement,(uint32_t *)0x0); + } else { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + vTaskNotifyGiveFromISR(xTaskToNotify, &xHigherPriorityTaskWoken); + if (xHigherPriorityTaskWoken != 0) { + vTaskSwitchContext(); + } + } +} + +void ipc_emb_wait(void) { + ulTaskNotifyTake(1, portMAX_DELAY); +} + +void ipc_emb_tx_flow_off(void) { + IPC->app2emb_unmask_clear = 0x1f00; + ke_evt_clear(0xf80); +} + +void ipc_emb_tx_flow_on(void) { + IPC->app2emb_unmask_set = 0x1f00; +} + +void ipc_emb_tx_irq(void) { + uint32_t status = IPC->app2emb_status; + if (status & 0x1f00) { + ke_evt_set(status >> 1); + IPC->app2emb_unmask_clear = status; + IPC->app2emb_ack = status; + } +} + +void ipc_emb_txdesc_copy(struct txdesc *dst_local, volatile struct txdesc_host *src_shared) { + for (int i = 0; i < sizeof(struct hostdesc); i++) { + *(uint32_t*)&dst_local->host = *(uint32_t*)&src_shared->host; + } +} + +void ipc_emb_tx_evt(int queue_idx) { + uint32_t event = ipc_emb_evt_bit[queue_idx]; + ke_evt_clear(event); + while (true) { + volatile struct txdesc_host* txdesc_hx = ipc_emb_env.txdesc + (ipc_emb_env.txdesc_idx & 3); + if (txdesc_hx->ready != 0xffffffff) { + IPC->app2emb_unmask_set = 0x100; + return ; + } + if (((event & 0x800) == 0) && ((ke_env.evt_field & 0x440800) != 0)) break; + IPC->app2emb_ack = 0x100; + struct txdesc* txdesc = (struct txdesc*)txdesc_hx->pad_txdesc; + memset(txdesc, 0, sizeof(struct txdesc)); + txdesc->hw_desc.cfm_ptr = &txdesc->hw_cfm; + txdesc->lmac.hw_desc = &txdesc->hw_desc; + ipc_emb_txdesc_copy(txdesc, txdesc_hx); + txdesc->lmac.agg_desc = 0; + txdesc->hw_desc.thd.nextmpdudesc_ptr = 0; + txdesc->hw_desc.thd.optlen[0] = 0; + txdesc->hw_desc.thd.optlen[1] = 0; + txdesc->hw_desc.thd.optlen[2] = 0; + txdesc->umac.buf_control = 0; + txu_cntrl_push(txdesc, 0); + txdesc_hx->ready = 1; + ipc_emb_env.txdesc_idx = ipc_emb_env.txdesc_idx + 1; + } + ke_evt_set(event); +} + +void ipc_emb_cfmback_irq(void) { + if (IPC->app2emb_status & 0x20) { + IPC->app2emb_unmask_clear = 0x20; + IPC->app2emb_ack = 0x20; + ke_evt_set(0x40000); + } + if (IPC->app2emb_status & 0x10) { + IPC->app2emb_unmask_clear = 0x10; + IPC->app2emb_ack = 0x10; + ke_evt_set(0x80000); + } +} + +bool ipc_emb_hostrxdesc_check(void) { + return 1; +} + +void ipc_emb_radar_event_ind(void) { + IPC->emb2app_trigger = 0x40; +} + +void ipc_emb_prim_tbtt_ind(void) { + IPC->emb2app_trigger = 0x10; +} + +void ipc_emb_sec_tbtt_ind(void) { + IPC->emb2app_trigger = 0x20; +} + +void ipc_emb_kmsg_hdlr(struct ke_msg *kmsg_ipc) { + struct ke_msg* kmsg_dst = ke_malloc(kmsg_ipc->param_len + sizeof(struct ke_msg)); + ASSERT_ERR(kmsg_dst != NULL); + kmsg_dst->hdr.next = NULL; + kmsg_dst->id = kmsg_ipc->id; + kmsg_dst->dest_id = kmsg_ipc->dest_id; + kmsg_dst->src_id = 13; + kmsg_dst->param_len = kmsg_ipc->param_len; + memcpy(kmsg_dst->param, kmsg_ipc->param, kmsg_dst->param_len); + kmsg_ipc->src_id = ipc_emb_env.ipc_msgacke2a_cnt++; + ipc_emb_env.ipc_msgacke2a_cnt = ipc_emb_env.ipc_msgacke2a_cnt; + ASSERT_ERR(ke_task_local(kmsg_dst->dest_id)); + IPC->emb2app_trigger = 4; + ke_msg_send(kmsg_dst + 1); +} + +void ipc_emb_msg_irq(void) { + if (IPC->app2emb_status & 2) { + ke_evt_set(0x2000000); + IPC->app2emb_unmask_clear = 2; + } +} + +void ipc_emb_msg_evt(int dummy) { + for (uint32_t rawstatus = IPC->app2emb_rawstatus; rawstatus & 2; rawstatus = IPC->app2emb_rawstatus) { + IPC->app2emb_ack = 2; + ipc_emb_kmsg_hdlr((struct ke_msg *)&ipc_shared_env.msg_a2e_buf); + } + ke_evt_clear(0x2000000); + IPC->app2emb_unmask_set = 2; +} diff --git a/src/bl602_wifi/driver/ipc/ipc_shared.c b/src/bl602_wifi/driver/ipc/ipc_shared.c new file mode 100644 index 0000000..5949185 --- /dev/null +++ b/src/bl602_wifi/driver/ipc/ipc_shared.c @@ -0,0 +1,3 @@ +#include + +struct ipc_shared_env_tag ipc_shared_env; // :24:27 \ No newline at end of file diff --git a/src/include/bl602_wifi/ipc/ipc_emb.h b/src/include/bl602_wifi/ipc/ipc_emb.h new file mode 100644 index 0000000..9d643e7 --- /dev/null +++ b/src/include/bl602_wifi/ipc/ipc_emb.h @@ -0,0 +1,33 @@ +#ifndef _IPC_EMB_H_ +#define _IPC_EMB_H_ + +#include +#include +#include + +struct ipc_emb_env_tag { + struct co_list rx_queue; // +0 + struct co_list cfm_queue; // +8 + uint8_t ipc_rxdesc_idx; // +16 + uint8_t ipc_rxbuf_idx; // +17 + uint8_t ipc_radar_buf_idx; // +18 + uint8_t ipc_msge2a_buf_idx; // +19 + uint8_t ipc_dbg_buf_idx; // +20 + uint8_t ipc_msgacke2a_cnt; // +21 + uint32_t txdesc_idx; // +24 + volatile struct txdesc_host *txdesc; // +28 +}; + + +extern struct ipc_emb_env_tag ipc_emb_env; +extern const int nx_txdesc_cnt_msk[]; + + +bool ipc_emb_tx_q_has_data(int queue_idx); +uint32_t ipc_emb_tx_evt_field(uint32_t stat); +void ipc_emb_txcfm_ind(uint32_t queue_bits); +void ipc_emb_init(void); +void ipc_emb_notify(void); +void ipc_emb_wait(void); + +#endif \ No newline at end of file diff --git a/src/include/bl602_wifi/ipc/ipc_shared.h b/src/include/bl602_wifi/ipc/ipc_shared.h new file mode 100644 index 0000000..94bf067 --- /dev/null +++ b/src/include/bl602_wifi/ipc/ipc_shared.h @@ -0,0 +1,19 @@ +#ifndef _IPC_SHARED_H_ +#define _IPC_SHARED_H_ +#include +#include +struct ipc_a2e_msg { + uint32_t dummy_word; // +0 + uint32_t msg[127]; // +4 +}; // :213:8 +#ifndef CFG_TXDESC +#define CFG_TXDESC 4 +#endif +#define NX_TXDESC_CNT0 CFG_TXDESC +struct ipc_shared_env_tag { + volatile struct ipc_a2e_msg msg_a2e_buf; // +0 + volatile uint32_t pattern_addr; // +512 + volatile struct txdesc_host txdesc0[4]; // +516 +}; // :244:8 +extern struct ipc_shared_env_tag ipc_shared_env; // :257:34 +#endif // _IPC_SHARED_H_ \ No newline at end of file diff --git a/src/include/bl602_wifi/la/la_mem.h b/src/include/bl602_wifi/la/la_mem.h new file mode 100644 index 0000000..5a9f460 --- /dev/null +++ b/src/include/bl602_wifi/la/la_mem.h @@ -0,0 +1,8 @@ +#ifndef _LA_MEM_H_ +#define _LA_MEM_H_ + +struct la_mem_format { + uint32_t word[4]; // +0 +}; // :37:8 + +#endif // _LA_MEM_H_ diff --git a/src/include/bl602_wifi/lmac/tx/tx_swdesc.h b/src/include/bl602_wifi/lmac/tx/tx_swdesc.h new file mode 100644 index 0000000..58a7c4a --- /dev/null +++ b/src/include/bl602_wifi/lmac/tx/tx_swdesc.h @@ -0,0 +1,71 @@ +#ifndef _TX_SWDESC_H_ +#define _TX_SWDESC_H_ + +#include +#include + +#include +#include +#include + + +struct hostdesc { + uint32_t pbuf_addr; // +0 + uint32_t packet_addr; // +4 + uint16_t packet_len; // +8 + uint32_t status_addr; // +12 + struct mac_addr eth_dest_addr; // +16 + struct mac_addr eth_src_addr; // +22 + uint16_t ethertype; // +28 + uint16_t pn[4]; // +30 + uint16_t sn; // +38 + uint16_t timestamp; // +40 + uint8_t tid; // +42 + uint8_t vif_idx; // +43 + uint8_t staid; // +44 + uint16_t flags; // +46 + uint32_t pbuf_chained_ptr[4]; // +48 + uint32_t pbuf_chained_len[4]; // +64 +}; + +struct umacdesc { + struct txl_buffer_control *buf_control; // +0 + uint32_t buff_offset; // +4 + uint16_t payl_len; // +8 + uint8_t head_len; // +10 + uint8_t hdr_len_802_2; // +11 + uint8_t tail_len; // +12 +}; + +struct lmacdesc { + struct tx_agg_desc *agg_desc; // +0 + struct txl_buffer_tag *buffer; // +4 + struct tx_hw_desc *hw_desc; // +8 +}; + +struct txdesc { + struct co_list_hdr list_hdr; // +0 + struct hostdesc host; // +4 + struct umacdesc umac; // +84 + struct lmacdesc lmac; // +100 + struct tx_hw_desc hw_desc; // +112 + struct tx_cfm_tag hw_cfm; // +184 + uint32_t buf[128]; // +204 +}; + +struct txdesc_host { + uint32_t ready; // +0 + struct hostdesc host; // +4 + uint32_t pad_txdesc[55]; // +84 + uint32_t pad_buf[128]; // +304 +}; + + +extern struct txdesc *txdesc_array; +extern const int nx_txdesc_cnt[5]; + + +bool is_int_frame(struct txdesc *txdesc); +bool is_qos_data(struct txdesc *txdesc); + +#endif diff --git a/src/include/bl602_wifi/modules/common/co_list.h b/src/include/bl602_wifi/modules/common/co_list.h new file mode 100644 index 0000000..e7600e8 --- /dev/null +++ b/src/include/bl602_wifi/modules/common/co_list.h @@ -0,0 +1,12 @@ +#ifndef _CO_LIST_H_ +#define _CO_LIST_H_ +struct co_list_hdr { + struct co_list_hdr *next; // +0 +}; // :47:8 + +struct co_list { + struct co_list_hdr *first; // +0 + struct co_list_hdr *last; // +4 +}; // :54:8 + +#endif // _CO_LIST_H_ diff --git a/src/include/bl602_wifi/modules/ke/ke_env.h b/src/include/bl602_wifi/modules/ke/ke_env.h new file mode 100644 index 0000000..1516f77 --- /dev/null +++ b/src/include/bl602_wifi/modules/ke/ke_env.h @@ -0,0 +1,21 @@ +#ifndef _KE_ENV_H_ +#define _KE_ENV_H_ + +#include + +#include + + +typedef uint32_t evt_field_t; + +struct ke_env_tag { + volatile evt_field_t evt_field; // +0 + struct co_list queue_sent; // +4 + struct co_list queue_saved; // +12 + struct co_list queue_timer; // +20 + struct mblock_free *mblock_first; // +28 +}; + +extern struct ke_env_tag ke_env; + +#endif diff --git a/src/include/bl602_wifi/modules/ke/ke_event.h b/src/include/bl602_wifi/modules/ke/ke_event.h new file mode 100644 index 0000000..4298011 --- /dev/null +++ b/src/include/bl602_wifi/modules/ke/ke_event.h @@ -0,0 +1,12 @@ +#ifndef _KE_EVENT_H_ +#define _KE_EVENT_H_ + +#include + +evt_field_t ke_evt_get(void); +void ke_evt_set(const evt_field_t event); +void ke_evt_clear(const evt_field_t event); +void ke_evt_schedule(void); +void ke_init(void); + +#endif diff --git a/src/include/bl602_wifi/modules/ke/ke_mem.h b/src/include/bl602_wifi/modules/ke/ke_mem.h new file mode 100644 index 0000000..07df734 --- /dev/null +++ b/src/include/bl602_wifi/modules/ke/ke_mem.h @@ -0,0 +1,11 @@ +#ifndef _KE_MEM_H_ +#define _KE_MEM_H_ + +#include + + +struct mblock_free *ke_mem_init(void); +void *ke_malloc(uint32_t size); +void ke_free(void *mem_ptr); + +#endif // _KE_MEM_H_ diff --git a/src/include/bl602_wifi/modules/ke/ke_msg.h b/src/include/bl602_wifi/modules/ke/ke_msg.h new file mode 100644 index 0000000..30b3097 --- /dev/null +++ b/src/include/bl602_wifi/modules/ke/ke_msg.h @@ -0,0 +1,41 @@ +#ifndef _KE_MSG_H_ +#define _KE_MSG_H_ + +#include +#include +#include + +#include + + +typedef uint16_t ke_task_id_t; +typedef uint16_t ke_state_t; +typedef uint16_t ke_msg_id_t; + +struct ke_msg { + struct co_list_hdr hdr; // +0 + ke_msg_id_t id; // +4 + ke_task_id_t dest_id; // +6 + ke_task_id_t src_id; // +8 + uint16_t param_len; // +10 + uint32_t param[]; // +12 +}; + +STATIC_ASSERT(sizeof(struct ke_msg) == 12, ke_msg_must_has_sizeof_12); + +enum ke_msg_status_tag { + KE_MSG_CONSUMED = 0, + KE_MSG_NO_FREE = 1, + KE_MSG_SAVED = 2 +}; + + +struct ke_msg *ke_param2msg(const void *param_ptr); +void *ke_msg2param(const struct ke_msg *msg); +void *ke_msg_alloc(const ke_msg_id_t id, const ke_task_id_t dest_id, const ke_task_id_t src_id, const uint16_t param_len); +void ke_msg_send(const void *param_ptr); +void ke_msg_send_basic(const ke_msg_id_t id, const ke_task_id_t dest_id, const ke_task_id_t src_id); +void ke_msg_forward_and_change_id(const void *param_ptr, const ke_msg_id_t msg_id, const ke_task_id_t dest_id, const ke_task_id_t src_id); +void ke_msg_free(const struct ke_msg *msg); + +#endif // _KE_MSG_H_ diff --git a/src/include/bl602_wifi/modules/ke/ke_task.h b/src/include/bl602_wifi/modules/ke/ke_task.h new file mode 100644 index 0000000..f26497b --- /dev/null +++ b/src/include/bl602_wifi/modules/ke/ke_task.h @@ -0,0 +1,74 @@ +#ifndef _KE_TASK_H_ +#define _KE_TASK_H_ + +#include +#include + +#include +#include + +// based on TASK_DESC +enum +{ + TASK_NONE = (uint8_t) -1, + + /// MAC Management task. + TASK_MM = 0, + TASK_DBG = 1, + /// SCAN task + TASK_SCAN = 2, + /// TDLS task + TASK_TDLS = 3, // maybe, not used anyway + /// SCAN task + TASK_SCANU = 4, + /// SCAN task + TASK_ME = 5, + /// SM task + TASK_SM = 6, + /// APM task + TASK_APM = 7, + /// BAM task + TASK_BAM = 8, + /// MESH task + TASK_MESH = 9, // maybe, not used anyway + TASK_HOSTAPD = 10, + /// RXU task + TASK_RXU = 11, // maybe, not used anyway + /// CFG task + TASK_CFG = 12, + // nX API task + TASK_API = 13, // maybe, not used anyway + TASK_MAX, // max == 14 +}; + +#define DRV_TASK_ID 100 + + +typedef int (*ke_msg_func_t)(const ke_msg_id_t, const void *, const ke_task_id_t, const ke_task_id_t); + +struct ke_msg_handler { + ke_msg_id_t id; // +0 + ke_msg_func_t func; // +4 +}; + +struct ke_state_handler { + const struct ke_msg_handler *msg_table; // +0 + uint16_t msg_cnt; // +4 +}; + +struct ke_task_desc { + const struct ke_state_handler *state_handler; // +0 + const struct ke_state_handler *default_handler; // +4 + ke_state_t *state; // +8 + uint16_t state_max; // +12 + uint16_t idx_max; // +14 +}; + +static bool ke_task_local(const ke_task_id_t id) { + ASSERT_ERR(id <= TASK_MAX); + return id < TASK_API; +}; +ke_state_t ke_state_get(const ke_task_id_t id); +void ke_state_set(const ke_task_id_t id, const ke_state_t state_id); + +#endif // __KE_TASK_H__ diff --git a/src/include/bl602_wifi/modules/mac/mac.h b/src/include/bl602_wifi/modules/mac/mac.h new file mode 100644 index 0000000..9f8e489 --- /dev/null +++ b/src/include/bl602_wifi/modules/mac/mac.h @@ -0,0 +1,99 @@ +#ifndef _MAC_H_ +#define _MAC_H_ + +#include +#include + + +struct mac_addr { + uint16_t array[3]; // +0 +}; + +struct mac_ssid { + uint8_t length; // +0 + uint8_t array[32]; // +1 + uint8_t array_tail[1]; // +33 +}; + +struct mac_rateset { + uint8_t length; // +0 + uint8_t array[12]; // +1 +}; + +struct key_info_tag { + uint64_t rx_pn[9]; // +0 + uint64_t tx_pn; // +72 + union { + struct { + uint32_t tx_key[2]; // +0 + uint32_t rx_key[2]; // +8 + } mic; + struct { + uint32_t key[4]; // +0 + } mfp; + } u; // +80 + uint8_t cipher; // +96 + uint8_t key_idx; // +97 + uint8_t hw_key_idx; // +98 + bool valid; // +99 +}; + +struct mac_sec_key { + uint8_t length; // +0 + uint32_t array[8]; // +4 +}; + +struct mac_htcapability { + uint16_t ht_capa_info; // +0 + uint8_t a_mpdu_param; // +2 + uint8_t mcs_rate[16]; // +3 + uint16_t ht_extended_capa; // +20 + uint32_t tx_beamforming_capa; // +24 + uint8_t asel_capa; // +28 +}; + +struct mac_vhtcapability { + uint32_t vht_capa_info; // +0 + uint16_t rx_mcs_map; // +4 + uint16_t rx_highest; // +6 + uint16_t tx_mcs_map; // +8 + uint16_t tx_highest; // +10 +}; + +struct mac_edca_param_set { + uint8_t qos_info; // +0 + uint8_t acm; // +1 + uint32_t ac_param[4]; // +4 +}; + +struct mac_scan_result { + struct mac_addr bssid; // +0 + struct mac_ssid ssid; // +6 + uint16_t bsstype; // +40 + struct scan_chan_tag *chan; // +44 + uint16_t beacon_period; // +48 + uint16_t cap_info; // +50 + bool valid_flag; // +52 + int8_t rssi; // +53 + int8_t ppm_rel; // +54 + int8_t ppm_abs; // +55 +}; + +struct mac_sta_info { + struct mac_rateset rate_set; // +0 + struct mac_htcapability ht_cap; // +16 + struct mac_vhtcapability vht_cap; // +48 + uint32_t capa_flags; // +60 + uint8_t phy_bw_max; // +64 + uint8_t bw_cur; // +65 + uint8_t uapsd_queues; // +66 + uint8_t max_sp_len; // +67 + uint8_t stbc_nss; // +68 +}; + +extern const uint8_t mac_tid2ac[]; +extern const uint8_t mac_ac2uapsd[4]; +extern const uint8_t mac_id2rate[]; +extern const struct mac_addr mac_addr_bcst; + +#endif diff --git a/src/include/bl602_wifi/umac/txu/txu_cntrl.h b/src/include/bl602_wifi/umac/txu/txu_cntrl.h new file mode 100644 index 0000000..1d9490c --- /dev/null +++ b/src/include/bl602_wifi/umac/txu/txu_cntrl.h @@ -0,0 +1,16 @@ +#ifndef __TXU_CNTRL_H__ +#define __TXU_CNTRL_H__ + +#include +#include + +#include + + +bool txu_cntrl_push(struct txdesc *txdesc, uint8_t access_category); +void txu_cntrl_frame_build(struct txdesc *txdesc, uint32_t buf); +void txu_cntrl_tkip_mic_append(struct txdesc *txdesc, uint8_t ac); +void txu_cntrl_cfm(struct txdesc *txdesc); +void txu_cntrl_protect_mgmt_frame(struct txdesc *txdesc, uint32_t frame, uint16_t hdr_len); + +#endif // __TXU_CNTRL_H__ From c1258fa78648e65aa6e59403c0cff94cf8e1ffce Mon Sep 17 00:00:00 2001 From: Fangfei Yang Date: Thu, 23 Dec 2021 05:24:33 -0600 Subject: [PATCH 081/148] bl602_demo_wifi.elf built w/o -Wl,--gc-sections --- blobs/bl602_demo_wifi.elf | Bin 7208192 -> 7384248 bytes 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 blobs/bl602_demo_wifi.elf diff --git a/blobs/bl602_demo_wifi.elf b/blobs/bl602_demo_wifi.elf old mode 100755 new mode 100644 index 332ecd51b9c347ffa15c053fd52cd687547ece1c..8b134819bd5257393c130995084df061dce65ad5 GIT binary patch delta 2825112 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
    VgHa5zyAX9*^H%-aFyBVg_ERFwj{ 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

    Ti+!H;>>)mJm1 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

    hpZ5DJM?ziL`h!_Y^O_d= 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�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≀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�P@FF)cZ&tdSS(#|N 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%0DdalKQNQs381SOUM;!3PQfRtEg(4fT2fJlj5 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

    Hiu8| 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