1 /*
2 * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "soc_random.h"
8 #include <esp_log.h>
9 #include <soc/system_reg.h>
10 #include <soc/syscon_reg.h>
11 #include <soc/apb_saradc_reg.h>
12 #include <soc/rtc_cntl_reg.h>
13 #include <soc/sens_reg.h>
14 #include <hal/regi2c_ctrl.h>
15 #include <soc/regi2c_saradc.h>
16
soc_random_enable(void)17 void soc_random_enable(void)
18 {
19 SET_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_WIFI_CLK_RNG_EN);
20
21 /* Enable 8M clock source for RNG (this is actually enough to produce strong random results,
22 * but enabling the SAR ADC as well adds some insurance.)
23 */
24 REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN);
25
26 /* Enable SAR ADC to read a disconnected input for additional entropy */
27
28 /* Reset ADC clock */
29 SET_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_APB_SARADC_CLK_EN);
30 CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_APB_SARADC_CLK_EN);
31
32 /* Enable clock and select clock source for ADC digital controller */
33 /* APB clock */
34 REG_SET_FIELD(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_SEL, 2);
35 SET_PERI_REG_MASK(APB_SARADC_CTRL_REG, APB_SARADC_SAR_CLK_GATED);
36 SET_PERI_REG_MASK(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_EN);
37
38 /* Read freq = apb_clk / (APB_SARADC_CLKM_DIV_NUM + 1) / TIMER_TARGET / 2
39 * Internal ADC sample freq = apb_clk / (APB_SARADC_CLKM_DIV_NUM + 1) /
40 * (APB_SARADC_SAR_CLK_DIV + 1) Read frequency has to be at least 35 times lower than the
41 * sampling frequency
42 */
43
44 REG_SET_FIELD(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLKM_DIV_NUM, 3);
45 /* SAR clock divider has to be at least 2 */
46 REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_SAR_CLK_DIV, 3);
47 REG_SET_FIELD(APB_SARADC_CTRL2_REG, APB_SARADC_TIMER_TARGET, 70);
48
49 CLEAR_PERI_REG_MASK(APB_SARADC_CTRL_REG, APB_SARADC_START_FORCE);
50 REG_SET_FIELD(SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR, 3);
51 CLEAR_PERI_REG_MASK(APB_SARADC_CTRL2_REG, APB_SARADC_MEAS_NUM_LIMIT);
52 REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_WORK_MODE, 1);
53
54 /* Test internal voltage if the channel info is 0xa. */
55 REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_SAR2_PATT_LEN, 0);
56 WRITE_PERI_REG(APB_SARADC_SAR2_PATT_TAB1_REG,
57 0xafffff);
58 /* Test internal voltage if the channel info is 0xa. */
59 REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_SAR1_PATT_LEN, 0);
60 WRITE_PERI_REG(APB_SARADC_SAR1_PATT_TAB1_REG,
61 0xafffff);
62
63 /* Enable adc1 digital controller */
64 SET_PERI_REG_MASK(SENS_SAR_MEAS1_MUX_REG, SENS_SAR1_DIG_FORCE);
65
66 /* Set SARADC2 arbiter */
67 CLEAR_PERI_REG_MASK(SENS_SAR_MEAS2_MUX_REG, SENS_SAR2_RTC_FORCE);
68 CLEAR_PERI_REG_MASK(APB_SARADC_APB_ADC_ARB_CTRL_REG, APB_SARADC_ADC_ARB_GRANT_FORCE);
69 CLEAR_PERI_REG_MASK(APB_SARADC_APB_ADC_ARB_CTRL_REG, APB_SARADC_ADC_ARB_FIX_PRIORITY);
70
71 /* Disable ADC filter */
72 REG_SET_FIELD(APB_SARADC_FILTER_CTRL0_REG, APB_SARADC_FILTER_CHANNEL0, 0xD);
73 REG_SET_FIELD(APB_SARADC_FILTER_CTRL0_REG, APB_SARADC_FILTER_CHANNEL1, 0xD);
74
75 /* Start ADC sample */
76 SET_PERI_REG_MASK(APB_SARADC_CTRL2_REG, APB_SARADC_TIMER_SEL);
77 SET_PERI_REG_MASK(APB_SARADC_CTRL2_REG, APB_SARADC_TIMER_EN);
78
79 /*Choose the appropriate internal voltage to measure*/
80 REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENCAL_REF_ADDR, 1);
81 REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_TSENS_ADDR, 1);
82 REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR, 0);
83 REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 0);
84 }
85
soc_random_disable(void)86 void soc_random_disable(void)
87 {
88 /* Restore internal I2C bus state */
89 REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENCAL_REF_ADDR, 0);
90 REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_TSENS_ADDR, 0);
91 REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR, 0);
92 REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 0);
93
94 /* Power off SAR ADC */
95 REG_SET_FIELD(SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR, 0);
96 /* return to ADC RTC controller */
97 CLEAR_PERI_REG_MASK(SENS_SAR_MEAS1_MUX_REG, SENS_SAR1_DIG_FORCE);
98 /* Invalidate ADC digital trigger timer */
99 CLEAR_PERI_REG_MASK(APB_SARADC_CTRL2_REG, APB_SARADC_TIMER_EN);
100
101 /* Disable ADC digital part */
102 CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_APB_SARADC_CLK_EN);
103 /* Hold reset bit for ADC digital part */
104 SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_APB_SARADC_RST);
105
106 /* Note: the 8M CLK entropy source continues running even after this function is called,
107 * but as mentioned above it's better to enable Wi-Fi or BT or call random_enable() in
108 * order to get a secondary entropy source.
109 */
110 }
111