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