WXK
2024-12-16 78e84fcf264afd731cd66c807d9fcb690fe12126
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
/**************************************************************************//**
 * @file     system_PanSeries.c
 * @version  V1.00
 * @brief    Panchip series SoC system clock init code and assert handler
 * @note
 * Copyright (C) 2020 Panchip Technology Corp. All rights reserved.
 *****************************************************************************/
#include "PanSeries.h"
#include "pan_clk.h"
#include "pan_fmc.h"
#include "pan_sys.h"
#include "pan_efuse.h"
 
/*
 * Global variables defined here should be used after RAM RW/ZI data init.
 */
uint32_t SystemCoreClock;
bool isFtDataValid = true;
float SocTemperature = 22; /* Treat default SoC temperature as 22 C */
/*
 * Global variables here to be used in SystemInit() function should reside
 * in flash, since RAM RW/ZI data are not initialized at that time.
 */
const uint32_t PanFlashLineMode = CONFIG_FLASH_LINE_MODE;
const bool PanFlashEnhanceEnable = false;
uint32_t vec_remap_adr = 0x20007000;
 
/**
  * @brief  Setup the microcontroller system
  *         Initialize the Embedded Flash Interface and other modules which should
  *         be init in early boot stage.
  * @param  None
  * @retval None
  */
void SystemInit(void)
{
    ANA->CPU_ADDR_REMAP_CTRL =0;
    
    // Speed up flash clock from default 16MHz to 32MHz
    CLK_SetFlashClkDiv(CLK_FLASH_CLKDIV_1);
    // Switch flash to 4-Line mode
    FMC_SetFlashMode(FLCTL, PanFlashLineMode, PanFlashEnhanceEnable);
    // Init I-Cache
    InitIcache(FLCTL, PanFlashLineMode);
 
#ifndef SYNC_3V_REG_MANUALLY
    // Auto sync value to 3v registers
    // Note that this auto-sync mechanism works for all registers needed
    // doing 3v sync except Px_DINOFF regs for P46/P47/P56 in GPIO module.
    CLK_Set3vSyncAuto();
#endif
 
#if CONFIG_SOC_DCDC_PAN1070
    uint32_t tmpreg = ANA->LP_BUCK_3V;
    // Increase buck default output voltage
    tmpreg &= (~ANAC_BUCK_VOUT_Msk_3v);
    tmpreg |= 0x6 << ANAC_BUCK_VOUT_Pos_3v;
    // Enable DCDC-LDO auto switching when SoC vbat voltage drop off to about 1.8v and then uprise again
    tmpreg |= ANAC_BUCK_VOL_LIMIT_EN_Msk_3v;
    // Enable buck output
    tmpreg &= ~0x1;
    ANA->LP_BUCK_3V = tmpreg;
#endif
 
    // Disable eFuse VDD for power saving purpose
    EFUSE->EF_VDD = 0;
    // Clear the internal XOCAP trim of XTH and we prefer to use the external capacitor instead
    CLK->XTH_CTRL &= ~CLK_XTHCTL_XO_CAP_SEL_Msk;
    // Disable SW pull-down res to avoid high power leakage in low temperature
    ANA->LP_SW &= ~ANAC_HP_DVDD_PD_Msk;
    // Forcely reset GPIO debounce clk source to AHB before configure db cycle
    GPIO_DB->DBCTL &= ~GP_DBCTL_DBCLKSRC_Msk;
    // Other optimization configs (From task 4372)
    ANA->LP_PTAT_POLY |= ANAC_PTAT_TMP_TRIM_Msk;
    CLK->XTL_CTRL_3V = (CLK->XTL_CTRL_3V & ~CLK_XTLCTL_CORE_BIAS_Msk_3v) | (0x7u << CLK_XTLCTL_CORE_BIAS_Pos_3v);
}
 
/**
  * @brief  Update SystemCoreClock variable according to Clock Register Values.
  *         The SystemCoreClock variable contains the core clock (HCLK), it can
  *         be used by the user application to setup the SysTick timer or configure
  *         other parameters.
  *
  * @note   Each time the core clock (HCLK) changes, this function must be called
  *         to update SystemCoreClock variable value. Otherwise, any configuration
  *         based on this variable will be incorrect.
  *
  * @param  None
  * @retval None
  */
void SystemCoreClockUpdate(void)
{
 
#ifdef FPGA_MODE
    //Fixed 32M System Clock on FPGA
    SystemCoreClock = FREQ_32MHZ;
#else
    uint32_t div = 0;
    uint32_t freq_out = 0;
        div = (CLK->CLK_TOP_CTRL_3V & CLK_TOPCTL_AHB_DIV_Msk) >> CLK_TOPCTL_AHB_DIV_Pos;
        if(div == 0)
            div = 1;
        else
            div += 1;
 
        if(CLK->CLK_TOP_CTRL_3V & CLK_SYS_SRCSEL_DPLL){
            freq_out = (CLK->DPLL_CTRL & CLK_DPLLCTL_FREQ_OUT_Msk);
            if(freq_out == CLK_DPLL_OUT_64M){
                SystemCoreClock = FREQ_64MHZ  / div;
            }
            else{
                SystemCoreClock = FREQ_48MHZ / div;
            }
        }
        else{
            SystemCoreClock = FREQ_32MHZ / div;
        }
#endif
}
 
static bool HwParamDataVerify(OTP_STRUCT_T *p_opt)
{
    uint8_t calc_checksum = 0;
 
    for (size_t i = 0x1E; i < 0x7B; i++)
    {
        calc_checksum += p_opt->d8[i];
    }
 
    if (calc_checksum != p_opt->m.ft_checksum)
    {
        return false;   // Calib data checksum failed
    }
 
    if (p_opt->m.ft_version >= 2)
    {
        calc_checksum = 0;
        for (size_t i = 0x80; i < 0xFF; i++)
        {
            calc_checksum += p_opt->d8[i];
        }
 
        if (calc_checksum != p_opt->m_v2.ft_checksum2)
        {
            return false;   // Calib data checksum2 failed
        }
    }
 
    return true;
}
 
__WEAK void ADC_SetCalirationParams(OTP_STRUCT_T *otp)
{
    return;
}
 
__WEAK void PW_ParamsSet(OTP_STRUCT_T *otp)
{
    return;
}
 
bool SystemHwParamLoader(OTP_STRUCT_T *otp)
{
    /*
     * NOTE: We should make sure flash enhance mode is disabled before read
     *       data from flash.
     */
    FMC_GetFlashUniqueId(FLCTL);
    FMC_GetFlashJedecId(FLCTL);
    FMC_SetFlashCapacity(FLCTL);
    FMC_ReadInfoArea(FLCTL, 0x0, CMD_DREAD, (uint8_t *)otp, sizeof(OTP_STRUCT_T));
 
    if (!HwParamDataVerify(otp))
    {
        /* Mark chip as NoFT */
        isFtDataValid = false;
        /* Exit if Hw Parameter Data Checking Failed */
        memset(&otp->d8[0x00], 0x00, sizeof(OTP_STRUCT_T));  // clear the global otp structure
        return false;
    }
 
    // Note:
    // 1. Clock XTH and XTL may need Board-Level calibration on customers MP stage
    // 2. ADC calibration data is loaded when calling ADC APIs (e.g. ADC_Init(), ADC_OutputVoltage(), ..)
    ANA->LP_PTAT_POLY = (ANA->LP_PTAT_POLY & ~(0x7u << 3) & ~(0x7u << 16)) | (otp->m.pmu_vbg_trim << 3) | (otp->m.ipoly_trim << 16);
    ANA->LP_HP_LDO = (ANA->LP_HP_LDO & ~(0xFu << 3) & ~(0x7u << 20)) | (otp->m.hp_ldo_trim << 3) | (otp->m.flash_ldo_trim << 20);
    ANA->LP_LP_LDO_3V = (ANA->LP_LP_LDO_3V & ~(0xFu << 1) & ~(0xFu << 17)) | (otp->m.lpl_ldo_trim << 1) | (otp->m.lph_ldo_trim << 17);
    ANA->LP_ANA_LDO = (ANA->LP_ANA_LDO & ~(0xFu << 3)) | (otp->m.ana_ldo_trim << 3);
    ANA->ANA_RFFE_LDO = (ANA->ANA_RFFE_LDO & ~(0xFu << 3)) | (otp->m.rffe_ldo_trim << 3);
    ANA->LP_FSYN_LDO = (ANA->LP_FSYN_LDO & ~(0xFu << 3)) | (otp->m.fsyn_ldo_trim << 3);
    ANA->ANA_ADC_LDO = (ANA->ANA_ADC_LDO & ~(0xFu << 3)) | (otp->m.adc_ldo_trim << 3);
    ANA->ANA_VCO_LDO = (ANA->ANA_VCO_LDO & ~(0xFu << 3)) | (otp->m.vco_ldo_trim << 3);
    ANA->ANA_MISC_3V = (ANA->ANA_MISC_3V & ~(0x7u << 0)) | (otp->m.bod_vref_trim << 0);
    CLK->RCH_CTRL = (CLK->RCH_CTRL & ~(0xFFu << 8)) | (otp->m.rch_trim << 8);
    CLK->RCL_CTRL_3V = (CLK->RCL_CTRL_3V & ~(0xFFFu << 4)) | (otp->m.rcl_coarse_trim << 4) | (otp->m.rcl_fine_trim << 8);
    otp->m.buck_imax_cal_trim = (otp->m.buck_imax_cal_trim + 4 > 0x1F) ? 0x1F : (otp->m.buck_imax_cal_trim + 4);
    ANA->ANA_RESERVED_3V = (ANA->ANA_RESERVED_3V & ~(0x1u << 21)) | ((otp->m.buck_out_trim & 0x1u) << 21);   // lsb of buck vout trim code
    ANA->LP_BUCK_3V = (ANA->LP_BUCK_3V & ~(0xFu << 2) & ~(0x1Fu << 9) & ~(0x1Fu << 14))
            | ((otp->m.buck_out_trim >> 1) << 2) | (otp->m.buck_imax_cal_trim << 9) | (otp->m.buck_zero_cal_trim << 14);
    ANA->ANA_DFT = (ANA->ANA_DFT & ~(0xFFu << 24)) | (otp->m.battery_trim << 24);
 
    if (otp->m.ft_version >= 2)
    {
        if (otp->m.ft_version < 4)
        {
            otp->m_v2.lph_ldo_vref_trim++;
            if (otp->m_v2.lph_ldo_vref_trim > 7)
            {
                otp->m_v2.lph_ldo_vref_trim = 7;
            }
        }
        ANA->LP_LP_LDO_3V = (ANA->LP_LP_LDO_3V & ~(0x7u << 21)) | (otp->m_v2.lph_ldo_vref_trim << 21);
        ANA->ANA_RESERVED_3V |= (0x1u << 24);  // LPLDOH enhance mode (default enabled, coordinate with lph vref trim)
        if (otp->m.ft_version >= 7)
        {
            // Start from this ft version, we change LPLDOH calibrate flow to MODE2 (indtead of MODE1 with enhance mode),
            // hence we should switch LPLDOH to MODE2 before we use it.
            // Note that lph_ldo_trim would take no effect anymore when we switch LPLDOH to MODE2
            ANA->LP_LP_LDO_3V |= ANAC_LPLDO_H_MODE_SEL_Msk_3v;
        }
    }
 
    if (otp->m.ft_version >= 6)
    {
        ANA->LP_PTAT_POLY = (ANA->LP_PTAT_POLY & ~(0x3u << 1)) | (otp->m_v2.ptat_temp_trim << 1);
        CLK->XTL_CTRL_3V = (CLK->XTL_CTRL_3V & ~(0x7u << 4)) | (otp->m_v2.xtl_core << 4);
        CLK->XTH_CTRL = (CLK->XTH_CTRL & ~(0x1u << 10)) | (otp->m_v2.xth_icore << 10);
        CLK->RCH_CTRL = (CLK->RCH_CTRL & ~(0x3u << 4)) | (otp->m_v2.rch_bias << 4);
        CLK->DPLL_CTRL = (CLK->DPLL_CTRL & ~(0x3u << 4) & ~(0x3u << 6) & ~(0x7u << 8) & ~(0x3u << 11))
            | (otp->m_v2.dpll_icp_bias << 4) | (otp->m_v2.dpll_icp_ctrl << 6)  | (otp->m_v2.dpll_kvco_ctrl << 8)  | (otp->m_v2.dpll_vco_freq_trim << 11);
    }
 
    /*
     * Storing adc params related calibration. if adc symbol is not linked, 
     * this function would be handled as weak function.
     */
    ADC_SetCalirationParams(otp);
 
    /*
     * Storing power params related calibration.
     */
    PW_ParamsSet(otp);
 
#ifdef SYNC_3V_REG_MANUALLY
    CLK_Wait3vSyncReady();
#endif
 
    return true;
}
 
 
#if USE_ASSERT
 
/**
 * @brief      Assert Error Message
 *
 * @param[in]  file  the source file name
 * @param[in]  line  line number
 *
 * @return     None
 *
 * @details    The function prints the source file name and line number where
 *             the ASSERT_PARAM() error occurs, and then stops in an infinite loop.
 */
void AssertError(uint8_t * file, uint32_t line)
{
 
    SYS_DBG(" wrong parameters.\r\n", file, line);
 
    /* Infinite loop */
    while(1) ;
}
#endif