From e036a7b745e524a36922405f992d35689a1bd9b8 Mon Sep 17 00:00:00 2001 From: hongshuqing Date: Wed, 31 Jul 2024 16:52:23 +0800 Subject: [PATCH] feat(bootloader): add rng support for ESP32-C61 --- .../src/bootloader_random_esp32c61.c | 101 ++++++++++++++++++ .../esp32c61/include/soc/Kconfig.soc_caps.in | 4 + .../soc/esp32c61/include/soc/regi2c_saradc.h | 79 ++++++++++++++ .../soc/esp32c61/include/soc/soc_caps.h | 3 + .../soc/esp32c61/include/soc/wdev_reg.h | 2 +- 5 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 components/bootloader_support/src/bootloader_random_esp32c61.c create mode 100644 components/soc/esp32c61/include/soc/regi2c_saradc.h diff --git a/components/bootloader_support/src/bootloader_random_esp32c61.c b/components/bootloader_support/src/bootloader_random_esp32c61.c new file mode 100644 index 0000000000..bcc7d57f16 --- /dev/null +++ b/components/bootloader_support/src/bootloader_random_esp32c61.c @@ -0,0 +1,101 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "sdkconfig.h" +#include "bootloader_random.h" +#include "soc/soc.h" +#include "soc/pcr_reg.h" +#include "soc/apb_saradc_reg.h" +#include "soc/pmu_reg.h" +#include "hal/regi2c_ctrl.h" +#include "soc/regi2c_saradc.h" +#include "esp_log.h" + +static const uint32_t SAR2_CHANNEL = 9; +static const uint32_t SAR1_CHANNEL = 7; +static const uint32_t PATTERN_BIT_WIDTH = 6; +static const uint32_t SAR1_ATTEN = 3; +static const uint32_t SAR2_ATTEN = 3; + +void bootloader_random_enable(void) +{ + // pull SAR ADC out of reset + REG_SET_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_RST_EN); + REG_CLR_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_RST_EN); + + // enable SAR ADC APB clock + REG_SET_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_REG_CLK_EN); + + // pull APB register out of reset + REG_SET_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_REG_RST_EN); + REG_CLR_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_REG_RST_EN); + + // enable ADC_CTRL_CLK (SAR ADC function clock) + REG_SET_BIT(PCR_SARADC_CLKM_CONF_REG, PCR_SARADC_CLKM_EN); + + // select XTAL clock (40 MHz) source for ADC_CTRL_CLK + REG_SET_FIELD(PCR_SARADC_CLKM_CONF_REG, PCR_SARADC_CLKM_SEL, 0); + + // set the clock divider for ADC_CTRL_CLK to default value (in case it has been changed) + REG_SET_FIELD(PCR_SARADC_CLKM_CONF_REG, PCR_SARADC_CLKM_DIV_NUM, 0); + + // some ADC sensor registers are in power group PERIF_I2C and need to be enabled via PMU + SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB); + SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C); + + // Config ADC circuit (Analog part) with I2C(HOST ID 0x69) and chose internal voltage as sampling source + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR , 0); + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR , 1); + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC1_ENCAL_REF_ADDR, 1); + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, 1); + + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_HIGH_ADDR, 0x08); + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_LOW_ADDR, 0x66); + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_HIGH_ADDR, 0x08); + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_LOW_ADDR, 0x66); + + // create patterns and set them in pattern table + uint32_t pattern_one = (SAR2_CHANNEL << 2) | SAR2_ATTEN; // we want channel 9 with max attenuation + uint32_t pattern_two = (SAR1_CHANNEL << 2) | SAR1_ATTEN; // we want channel 7 with max attenuation + uint32_t pattern_table = 0 | (pattern_two << 3 * PATTERN_BIT_WIDTH) | pattern_one << 2 * PATTERN_BIT_WIDTH; + REG_WRITE(SARADC_SAR_PATT_TAB1_REG, pattern_table); + + // set pattern length to 2 (APB_SARADC_SAR_PATT_LEN counts from 0) + REG_SET_FIELD(SARADC_CTRL_REG, SARADC_SAR_PATT_LEN, 1); + + // Same as in C3 + REG_SET_FIELD(SARADC_CTRL_REG, SARADC_SAR_CLK_DIV, 15); + + // set timer expiry (timer is ADC_CTRL_CLK) + REG_SET_FIELD(SARADC_CTRL2_REG, SARADC_TIMER_TARGET, 200); + + // enable timer + REG_SET_BIT(SARADC_CTRL2_REG, SARADC_TIMER_EN); +} + +void bootloader_random_disable(void) +{ + // disable timer + REG_CLR_BIT(SARADC_CTRL2_REG, SARADC_TIMER_EN); + + // Write reset value of this register + REG_WRITE(SARADC_SAR_PATT_TAB1_REG, 0xFFFFFF); + + // Revert ADC I2C configuration and initial voltage source setting + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_HIGH_ADDR, 0x60); + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_LOW_ADDR, 0x0); + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_HIGH_ADDR, 0x60); + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_LOW_ADDR, 0x0); + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 0); + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR, 0); + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC1_ENCAL_REF_ADDR, 0); + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, 0); + + // disable ADC_CTRL_CLK (SAR ADC function clock) + REG_WRITE(PCR_SARADC_CLKM_CONF_REG, 0x00404000); + + // Set PCR_SARADC_CONF_REG to initial state + REG_WRITE(PCR_SARADC_CONF_REG, 0x5); +} diff --git a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in index 5f96bc2684..d4eeacf2de 100644 --- a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in @@ -103,6 +103,10 @@ config SOC_BROWNOUT_RESET_SUPPORTED bool default y +config SOC_RNG_SUPPORTED + bool + default y + config SOC_SHARED_IDCACHE_SUPPORTED bool default y diff --git a/components/soc/esp32c61/include/soc/regi2c_saradc.h b/components/soc/esp32c61/include/soc/regi2c_saradc.h new file mode 100644 index 0000000000..c7137f3bb0 --- /dev/null +++ b/components/soc/esp32c61/include/soc/regi2c_saradc.h @@ -0,0 +1,79 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +/** + * @file regi2c_saradc.h + * @brief Register definitions for analog to calibrate initial code for getting a more precise voltage of SAR ADC. + * + * This file lists register fields of SAR, located on an internal configuration + * bus. These definitions are used via macros defined in regi2c_ctrl.h, by + * function in adc_ll.h. + */ + +#define I2C_SAR_ADC 0X69 +#define I2C_SAR_ADC_HOSTID 0 + +#define ADC_SAR1_ENCAL_GND_ADDR 0x7 +#define ADC_SAR1_ENCAL_GND_ADDR_MSB 5 +#define ADC_SAR1_ENCAL_GND_ADDR_LSB 5 + +#define ADC_SAR2_ENCAL_GND_ADDR 0x7 +#define ADC_SAR2_ENCAL_GND_ADDR_MSB 7 +#define ADC_SAR2_ENCAL_GND_ADDR_LSB 7 + +#define ADC_SAR1_INITIAL_CODE_HIGH_ADDR 0x1 +#define ADC_SAR1_INITIAL_CODE_HIGH_ADDR_MSB 0x3 +#define ADC_SAR1_INITIAL_CODE_HIGH_ADDR_LSB 0x0 + +#define ADC_SAR1_INITIAL_CODE_LOW_ADDR 0x0 +#define ADC_SAR1_INITIAL_CODE_LOW_ADDR_MSB 0x7 +#define ADC_SAR1_INITIAL_CODE_LOW_ADDR_LSB 0x0 + +#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR 0x4 +#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR_MSB 0x3 +#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR_LSB 0x0 + +#define ADC_SAR2_INITIAL_CODE_LOW_ADDR 0x3 +#define ADC_SAR2_INITIAL_CODE_LOW_ADDR_MSB 0x7 +#define ADC_SAR2_INITIAL_CODE_LOW_ADDR_LSB 0x0 + +#define ADC_SAR1_DREF_ADDR 0x2 +#define ADC_SAR1_DREF_ADDR_MSB 0x6 +#define ADC_SAR1_DREF_ADDR_LSB 0x4 + +#define ADC_SAR2_DREF_ADDR 0x5 +#define ADC_SAR2_DREF_ADDR_MSB 0x6 +#define ADC_SAR2_DREF_ADDR_LSB 0x4 + +#define ADC_SAR1_SAMPLE_CYCLE_ADDR 0x2 +#define ADC_SAR1_SAMPLE_CYCLE_ADDR_MSB 0x2 +#define ADC_SAR1_SAMPLE_CYCLE_ADDR_LSB 0x0 + +#define ADC_SARADC_DTEST_RTC_ADDR 0x7 +#define ADC_SARADC_DTEST_RTC_ADDR_MSB 1 +#define ADC_SARADC_DTEST_RTC_ADDR_LSB 0 + +#define ADC_SARADC_ENT_TSENS_ADDR 0x7 +#define ADC_SARADC_ENT_TSENS_ADDR_MSB 2 +#define ADC_SARADC_ENT_TSENS_ADDR_LSB 2 + +#define ADC_SARADC_ENT_RTC_ADDR 0x7 +#define ADC_SARADC_ENT_RTC_ADDR_MSB 3 +#define ADC_SARADC_ENT_RTC_ADDR_LSB 3 + +#define ADC_SARADC1_ENCAL_REF_ADDR 0x7 +#define ADC_SARADC1_ENCAL_REF_ADDR_MSB 4 +#define ADC_SARADC1_ENCAL_REF_ADDR_LSB 4 + +#define ADC_SARADC2_ENCAL_REF_ADDR 0x7 +#define ADC_SARADC2_ENCAL_REF_ADDR_MSB 6 +#define ADC_SARADC2_ENCAL_REF_ADDR_LSB 6 + +#define I2C_SARADC_TSENS_DAC 0x6 +#define I2C_SARADC_TSENS_DAC_MSB 3 +#define I2C_SARADC_TSENS_DAC_LSB 0 diff --git a/components/soc/esp32c61/include/soc/soc_caps.h b/components/soc/esp32c61/include/soc/soc_caps.h index 69b3dfe8a4..2c8b115d01 100644 --- a/components/soc/esp32c61/include/soc/soc_caps.h +++ b/components/soc/esp32c61/include/soc/soc_caps.h @@ -132,6 +132,9 @@ /*-------------------------- BROWNOUT CAPS -----------------------------------*/ #define SOC_BROWNOUT_RESET_SUPPORTED 1 +/*-------------------------- RNG CAPS -----------------------------------*/ +#define SOC_RNG_SUPPORTED 1 + /*-------------------------- CACHE CAPS --------------------------------------*/ #define SOC_SHARED_IDCACHE_SUPPORTED 1 //Shared Cache for both instructions and data #define SOC_CACHE_WRITEBACK_SUPPORTED 1 diff --git a/components/soc/esp32c61/include/soc/wdev_reg.h b/components/soc/esp32c61/include/soc/wdev_reg.h index 180ec72469..bc1329c7a1 100644 --- a/components/soc/esp32c61/include/soc/wdev_reg.h +++ b/components/soc/esp32c61/include/soc/wdev_reg.h @@ -10,4 +10,4 @@ #include "soc/lpperi_reg.h" /* Hardware random number generator register */ -#define WDEV_RND_REG LPPERI_RNG_DATA_REG +#define WDEV_RND_REG LPPERI_RNG_DATA_SYNC_REG