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 <soc/soc.h>
9 #include <soc/pcr_reg.h>
10 #include <soc/apb_saradc_reg.h>
11 #include <soc/pmu_reg.h>
12 #include <hal/regi2c_ctrl.h>
13 #include <soc/regi2c_saradc.h>
14 #include <esp_log.h>
15 
16 static const uint32_t SAR2_CHANNEL = 9;
17 static const uint32_t PATTERN_BIT_WIDTH = 6;
18 static const uint32_t SAR1_ATTEN = 1;
19 static const uint32_t SAR2_ATTEN = 1;
20 
soc_random_enable(void)21 void soc_random_enable(void)
22 {
23 	/* pull SAR ADC out of reset */
24 	REG_SET_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_RST_EN);
25 	REG_CLR_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_RST_EN);
26 
27 	/* enable SAR ADC APB clock */
28 	REG_SET_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_REG_CLK_EN);
29 
30 	/* enable ADC_CTRL_CLK (SAR ADC function clock) */
31 	REG_SET_BIT(PCR_SARADC_CLKM_CONF_REG, PCR_SARADC_CLKM_EN);
32 
33 	/* select XTAL clock (40 MHz) source for ADC_CTRL_CLK */
34 	REG_SET_FIELD(PCR_SARADC_CLKM_CONF_REG, PCR_SARADC_CLKM_SEL, 0);
35 
36 	/* set the clock divider for ADC_CTRL_CLK to default value (in case it has been changed) */
37 	REG_SET_FIELD(PCR_SARADC_CLKM_CONF_REG, PCR_SARADC_CLKM_DIV_NUM, 0);
38 
39 	/* some ADC sensor registers are in power group PERIF_I2C and need to be enabled via PMU */
40 	SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB);
41 	SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C);
42 
43 	/* Config ADC circuit (Analog part) with I2C(HOST ID 0x69) and chose internal voltage as
44 	 * sampling source
45 	 */
46 	REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 2);
47 	REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR, 1);
48 	REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC1_ENCAL_REF_ADDR, 1);
49 	REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, 1);
50 
51 	REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_HIGH_ADDR, 0x08);
52 	REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_LOW_ADDR, 0x66);
53 	REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_HIGH_ADDR, 0x08);
54 	REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_LOW_ADDR, 0x66);
55 
56 	/* create patterns and set them in pattern table */
57 	/* we want channel 9 with max attenuation */
58 	uint32_t pattern_one = (SAR2_CHANNEL << 2) | SAR2_ATTEN;
59 	/* we want channel 0 with max attenuation, channel */
60 	uint32_t pattern_two = SAR1_ATTEN;
61 	/* doesn't really matter here */
62 	uint32_t pattern_table =
63 		0 | (pattern_two << 3 * PATTERN_BIT_WIDTH) | pattern_one << 2 * PATTERN_BIT_WIDTH;
64 	REG_WRITE(APB_SARADC_SAR_PATT_TAB1_REG, pattern_table);
65 
66 	/* set pattern length to 2 (APB_SARADC_SAR_PATT_LEN counts from 0) */
67 	REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_SARADC_SAR_PATT_LEN, 1);
68 
69 	/* Same as in C3 */
70 	REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_SARADC_SAR_CLK_DIV, 15);
71 
72 	/* set timer expiry (timer is ADC_CTRL_CLK) */
73 	REG_SET_FIELD(APB_SARADC_CTRL2_REG, APB_SARADC_SARADC_TIMER_TARGET, 200);
74 
75 	/* enable timer */
76 	REG_SET_BIT(APB_SARADC_CTRL2_REG, APB_SARADC_SARADC_TIMER_EN);
77 }
78 
soc_random_disable(void)79 void soc_random_disable(void)
80 {
81 	/* disable timer */
82 	REG_CLR_BIT(APB_SARADC_CTRL2_REG, APB_SARADC_SARADC_TIMER_EN);
83 
84 	/* Write reset value of this register */
85 	REG_WRITE(APB_SARADC_SAR_PATT_TAB1_REG, 0xFFFFFF);
86 
87 	/* Revert ADC I2C configuration and initial voltage source setting */
88 	REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_HIGH_ADDR, 0x60);
89 	REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_LOW_ADDR, 0x0);
90 	REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_HIGH_ADDR, 0x60);
91 	REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_LOW_ADDR, 0x0);
92 	REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 0);
93 	REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR, 0);
94 	REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC1_ENCAL_REF_ADDR, 0);
95 	REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, 0);
96 
97 	/* Revert PMU_RF_PWC_REG to it's initial value */
98 	CLEAR_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB);
99 
100 	/* disable ADC_CTRL_CLK (SAR ADC function clock) */
101 	REG_WRITE(PCR_SARADC_CLKM_CONF_REG, 0x00404000);
102 
103 	/* Set PCR_SARADC_CONF_REG to initial state */
104 	REG_WRITE(PCR_SARADC_CONF_REG, 0x5);
105 }
106