aboutsummaryrefslogtreecommitdiff
path: root/src/mcu/peripheral/rtl876x_lpc.c
blob: 26c15a3a70e24bb5af59c5bd60950d1b35b36ad8 (plain)
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
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
/**
**********************************************************************************************************
*               Copyright(c) 2020, Realtek Semiconductor Corporation. All rights reserved.
**********************************************************************************************************
* @file     rtl876x_lpc.c
* @brief    This file provides all the lpcomp firmware functions.
* @details
* @author   yuan
* @date     2020-11-16
* @version  v1.0.1
*********************************************************************************************************
*/

/* Includes ------------------------------------------------------------------*/
#include "rtl876x_lpc.h"

/* Internal defines ------------------------------------------------------------*/
/* Fast operation register address defines */
#define REG_FAST_WRITE_BASE_ADDR    (0x40000100UL)
#define REG_LPC_FAST_WDATA          (0x400001f0UL)
#define REG_LPC_FAST_ADDR           (0x400001f4UL)
#define REG_LPC_WR_STROBE           (0x400001f8UL)
/* AON register address defines */
#define LPC_AON_52                  (0x52)
#define LPC_AON_114                 (0x114)

/**
  * @brief  Fast write LPC register
  * @param  address: the address of LPC register .
  * @param  data: dta which write to LPC register.
  * @retval None
  */
void LPC_WriteReg(uint32_t offset, uint32_t data)
{
    static bool is_called = false;

    if (is_called == false)
    {
        *((volatile uint32_t *)0x40000014) |= BIT(9);//no need run this every time
        is_called = true;
    }

    /* Write data */
    *((volatile uint32_t *)REG_LPC_FAST_WDATA) = data;
    /* Write RTC register address. Only offset */
    *((volatile uint32_t *)REG_LPC_FAST_ADDR) = offset - REG_FAST_WRITE_BASE_ADDR;
    *((volatile uint32_t *)REG_LPC_WR_STROBE) = 1;
}

/**
  * @brief  Reset LPC.
  * @param  None
  * @return None
  */
void LPC_DeInit(void)
{
    /* Disable the LPC power */
    uint16_t reg_value = btaon_fast_read_safe(LPC_AON_114);
    reg_value &= LPC_AON_114_POWER_EN_CLR;
    btaon_fast_write_safe(LPC_AON_114, reg_value);

    /* Stop LPC counter */
    LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), (LPC->LPC_CR0 & LPC_COUNTER_START_CLR));

    /* Disable out signal */
    LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), (LPC->LPC_CR0 & LPC_LPCOMP_OUTPUT_EN_CLR));

    /* Disable int signal */
    LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), (LPC->LPC_CR0 & LPC_INT_LPCOMP_AON_EN_CLR));
    LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), (LPC->LPC_CR0 & LPC_INT_LPCOMP_NV_EN_CLR));
    LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), (LPC->LPC_CR0 & LPC_INT_LPCOMP_CNT_EN_CLR));

    /* Clear LPC comp value */
    LPC_WriteReg((uint32_t)(&(LPC->LPC_CMP)), 0);

    /* Reset counter */
    LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), LPC->LPC_CR0 | LPC_COUNTER_RESET_Msk);
    __NOP();
    __NOP();
    LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), LPC->LPC_CR0 & LPC_COUNTER_RESET_CLR);
}

/**
  * @brief  Initializes LPC peripheral according to
  *    the specified parameters in the LPC_InitStruct.
  * @param  LPC_InitStruct: pointer to a LPC_InitTypeDef
  *    structure that contains the configuration information for the
  *    specified LPC peripheral.
  * @retval None
  */
void LPC_Init(LPC_InitTypeDef *LPC_InitStruct)
{
    uint16_t reg_value = 0;

    /* Check the parameters */
    assert_param(IS_LPC_CHANNEL(LPC_InitStruct->LPC_Channel));
    assert_param(IS_LPC_EDGE(LPC_InitStruct->LPC_Edge));
    assert_param(IS_LPC_THRESHOLD(LPC_InitStruct->LPC_Threshold));

    /* Configure parameters */
    reg_value = btaon_fast_read_safe(LPC_AON_52);
    reg_value &= LPC_AON_52_THRESHOLD_Clr;
    reg_value |= LPC_InitStruct->LPC_Threshold & LPC_AON_52_THRESHOLD_Msk;
    btaon_fast_write_safe(LPC_AON_52, reg_value);

    reg_value = btaon_fast_read_safe(LPC_AON_114);
    reg_value &= LPC_AON_114_DEFAULT_Clr;
    reg_value |= ((LPC_InitStruct->LPC_Channel) << LPC_AON_114_CH_NUM_Pos) | \
                 (LPC_InitStruct->LPC_Edge);
    btaon_fast_write_safe(LPC_AON_114, reg_value);

    LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), LPC->LPC_CR0 | LPC_LPCOMP_CNT_CLEAR_Msk);
    __NOP();
    __NOP();
    LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), LPC->LPC_CR0 & LPC_LPCOMP_CNT_CLEAR_CLR);
}

/**
  * @brief  Fills each LPC_InitStruct member with its default value.
  * @param  LPC_InitStruct : pointer to a LPC_InitTypeDef structure which will be initialized.
  * @retval None
  */
void LPC_StructInit(LPC_InitTypeDef *LPC_InitStruct)
{
    LPC_InitStruct->LPC_Channel   = LPC_CHANNEL_P2_2;
    LPC_InitStruct->LPC_Edge      = LPC_Vin_Below_Vth;
    LPC_InitStruct->LPC_Threshold = LPC_2000_mV;
}

/**
  * @brief  Enables or disables LPC peripheral.
  * @param  NewState: new state of LPC peripheral.
  *     This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void LPC_Cmd(FunctionalState NewState)
{
    uint16_t reg_value = 0;

    /* Check the parameters */
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        /* Enable the LPC power */
        reg_value = btaon_fast_read_safe(LPC_AON_114);
        reg_value |= LPC_AON_114_POWER_EN_Msk;
        btaon_fast_write_safe(LPC_AON_114, reg_value);
    }
    else
    {
        /* Disable the LPC power */
        reg_value = btaon_fast_read_safe(LPC_AON_114);
        reg_value &= LPC_AON_114_POWER_EN_CLR;
        btaon_fast_write_safe(LPC_AON_114, reg_value);
    }
}

/**
  * @brief Start or stop the LPC counter.
  * @param  NewState: new state of the LPC counter.
  *   This parameter can be one of the following values:
  *     @arg ENABLE: Start LPCOMP counter.
  *     @arg DISABLE: Stop LPCOMP counter.
  * @retval None
  */
void LPC_CounterCmd(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        /* Start the LPCOMP counter */
        LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), ((LPC->LPC_CR0) | LPC_COUNTER_START_Msk));
    }
    else
    {
        /* Stop the LPCOMP counter */
        LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), ((LPC->LPC_CR0) & (LPC_COUNTER_START_CLR)));
    }
}

/**
  * @brief  Enables or disables the specified LPC interrupts.
  * @param  LPC_INT: specifies the LPC interrupt source to be enabled or disabled.
  *   This parameter can be one of the following values:
  *     @arg LPC_INT_LPCOMP_VOL: voltage detection interrupt.
  *     @arg LPC_INT_LPCOMP_CNT: low power comparator couter interrupt.
  * @param  NewState: new state of the specified LPC interrupt.
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void LPC_INTConfig(uint32_t LPC_INT, FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_LPC_CONFIG_INT(LPC_INT));
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        /* Enable the selected LPC interrupt */
        LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), ((LPC->LPC_CR0) | LPC_INT));
    }
    else
    {
        /* Disable the selected LPC interrupt */
        LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), ((LPC->LPC_CR0) & (~LPC_INT)));
    }
}

/**
  * @brief  Enable interrupt signal to CPU NVIC.
  * @param  This parameter can be: ENABLE or DISABLE.
  * @return None.
  */
void LPC_INTCmd(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), (LPC->LPC_CR0 | LPC_INT_LPCOMP_NV_EN_Msk));
    }
    else
    {
        LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), (LPC->LPC_CR0 & LPC_INT_LPCOMP_NV_EN_CLR));
    }
}

/**
  * @brief  Enable wakeup signal to power sequence.
  * @param  This parameter can be: ENABLE or DISABLE.
  * @return None.
  */
void LPC_WKCmd(FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), (LPC->LPC_CR0 | LPC_INT_LPCOMP_AON_EN_Msk));
    }
    else
    {
        LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), (LPC->LPC_CR0 & LPC_INT_LPCOMP_AON_EN_CLR));
    }
}

/**
  * @brief  Configure LPCOMP counter's comparator value.
  * @param  value: LPCOMP counter's comparator value which can be 0 to 0xfff.
  * @retval None
  */
void LPC_SetCompValue(uint32_t value)
{
    LPC_WriteReg((uint32_t) & (LPC->LPC_CMP), (value & 0xFFF));
}

/**
  * @brief  Reset the LPC counter.
  * @retval none
  */
void LPC_ResetCounter(void)
{
    /* Reset the LPCOMP counter */
    LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), (LPC->LPC_CR0 | LPC_COUNTER_RESET_Msk));
    __NOP();
    __NOP();
    LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), (LPC->LPC_CR0 & LPC_COUNTER_RESET_CLR));
}

/**
  * @brief  Checks whether the specified LPC interrupt is set or not.
  * @param  LPC_FLAG: specifies the LPC interrupt to check.
  *     This parameter can be one of the following values:
  *     @arg LPC_FLAG_LPCOMP_AON: couter comparator AON flag.
  *     @arg LPC_FLAG_LPCOMP_CNT: couter comparator flag.
  * @retval The new state of SPI_IT (SET or RESET).
  */
FlagStatus LPC_GetFlagStatus(uint32_t LPC_FLAG)
{
    ITStatus int_status = RESET;

    /* Check the parameters */
    assert_param(IS_LPC_STATUS_INT(LPC_FLAG));

    if (LPC_FLAG == LPC_FLAG_LPCOMP_AON)
    {
        if (((LPC->LPC_SR) & LPC_LPCOMP_OUTPUT_AON_Msk) != (uint32_t)RESET)
        {
            int_status = SET;
        }
    }
    else if (LPC_FLAG == LPC_FLAG_LPCOMP_CNT)
    {
        if (((LPC->LPC_SR) & LPC_LPCOMP_CNT_Msk) != (uint32_t)RESET)
        {
            int_status = SET;
        }
    }

    /* Return the LPC_FLAG status */
    return  int_status;
}

/**
  * @brief  Clear the specified LPC interrupt.
  * @param  LPC_FLAG: specifies the LPC interrupt to clear.
  *   This parameter can be one of the following values:
  *     @arg LPC_INT_COUNT_COMP: couter comparator interrupt.
  * @retval None
  */
void LPC_ClearFlag(uint32_t LPC_FLAG)
{
    /* Check the parameters */
    assert_param(IS_LPC_CLEAR_INT(LPC_FLAG));

    /* Clear counter comparator interrupt */
    if (LPC_FLAG == LPC_FLAG_LPCOMP_CNT)
    {
        LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), ((LPC->LPC_CR0) | LPC_LPCOMP_CNT_CLEAR_Msk));
        __NOP();
        __NOP();
        LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), (LPC->LPC_CR0 & LPC_LPCOMP_CNT_CLEAR_CLR));
    }
}

/**
  * @brief  Checks whether the specified LPC interrupt is set or not.
  * @param  LPC_INT: specifies the LPC interrupt to check.
  *     This parameter can be one of the following values:
  *     @arg LPC_INT_COUNT_COMP: couter comparator interrupt.
  * @retval The new state of SPI_IT (SET or RESET).
  */
ITStatus LPC_GetINTStatus(uint32_t LPC_INT)
{
    ITStatus int_status = RESET;

    /* Check the parameters */
    assert_param(IS_LPC_STATUS_INT(LPC_INT));

    if (LPC_INT == LPC_INT_LPCOMP_CNT)
    {
        if (((LPC->LPC_SR) & LPC_LPCOMP_CNT_Msk) != (uint32_t)RESET)
        {
            int_status = SET;
        }
    }

    /* Return the LPC_INT status */
    return  int_status;
}

/**
  * @brief  Clear the specified LPC interrupt.
  * @param  LPC_INT: specifies the LPC interrupt to clear.
  *   This parameter can be one of the following values:
  *     @arg LPC_INT_COUNT_COMP: couter comparator interrupt.
  * @retval None.
  */
void LPC_ClearINTPendingBit(uint32_t LPC_INT)
{
    /* Check the parameters */
    assert_param(IS_LPC_CLEAR_INT(LPC_INT));

    /* Clear counter comparator interrupt */
    if (LPC_INT == LPC_INT_LPCOMP_CNT)
    {
        LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), ((LPC->LPC_CR0) | LPC_LPCOMP_CNT_CLEAR_Msk));
        __NOP();
        __NOP();
        LPC_WriteReg((uint32_t)(&(LPC->LPC_CR0)), (LPC->LPC_CR0 & LPC_LPCOMP_CNT_CLEAR_CLR));
    }
}
/******************* (C) COPYRIGHT 2020 Realtek Semiconductor Corporation *****END OF FILE****/