From 4acac3e9efe49f84a2af4249c9e4fa124b1dc7d5 Mon Sep 17 00:00:00 2001 From: Mohamed ElShahawi Date: Sat, 23 May 2020 15:46:29 +0200 Subject: [PATCH] drivers: esp32/clock_control: Add Clock Driver - Support PLL for Higher Frequencies 80,160,240 MHz - Support XTAL Frequencies 26MHz, 40MHz - Clock Driver can't be disabled, because all of the other drivers will depend on it to get their operating Frequency based on chosen clock source (XTAL/PLL). - Add needed references to BBPLL i2c bus ROM functions. - Add `rtc` node to Device Tree. - Since All Peripherals Frequency is depending on CPU_CLK Source, `clock-source` property added to CPU node Signed-off-by: Mohamed ElShahawi --- CODEOWNERS | 1 + boards/xtensa/esp32/esp32.dts | 4 +- boards/xtensa/esp32/esp32_defconfig | 1 + drivers/clock_control/CMakeLists.txt | 1 + drivers/clock_control/Kconfig | 2 + drivers/clock_control/Kconfig.esp32 | 10 + drivers/clock_control/clock_control_esp32.c | 321 ++++++++++++++++++ drivers/clock_control/clock_control_esp32.h | 68 ++++ dts/bindings/clock/espressif,esp32-rtc.yaml | 31 ++ .../cpu/cadence,tensilica-xtensa-lx6.yaml | 6 + dts/xtensa/espressif/esp32.dtsi | 13 + include/dt-bindings/clock/esp32_clock.h | 84 +++++ soc/xtensa/esp32/Kconfig.soc | 2 + soc/xtensa/esp32/linker.ld | 3 + soc/xtensa/esp32/soc.h | 5 + 15 files changed, 550 insertions(+), 2 deletions(-) create mode 100644 drivers/clock_control/Kconfig.esp32 create mode 100644 drivers/clock_control/clock_control_esp32.c create mode 100644 drivers/clock_control/clock_control_esp32.h create mode 100644 dts/bindings/clock/espressif,esp32-rtc.yaml create mode 100644 include/dt-bindings/clock/esp32_clock.h diff --git a/CODEOWNERS b/CODEOWNERS index 76bbf80bdf..423642b74d 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -141,6 +141,7 @@ /drivers/can/ @alexanderwachter /drivers/can/*mcp2515* @karstenkoenig /drivers/clock_control/*nrf* @nordic-krch +/drivers/clock_control/*esp32* @extremegtx /drivers/counter/ @nordic-krch /drivers/console/semihost_console.c @luozhongyao /drivers/counter/counter_cmos.c @andrewboie diff --git a/boards/xtensa/esp32/esp32.dts b/boards/xtensa/esp32/esp32.dts index aab8efb17b..9084426b77 100644 --- a/boards/xtensa/esp32/esp32.dts +++ b/boards/xtensa/esp32/esp32.dts @@ -24,11 +24,11 @@ }; &cpu0 { - clock-frequency = <40000000>; + clock-frequency = ; }; &cpu1 { - clock-frequency = <40000000>; + clock-frequency = ; }; &uart0 { diff --git a/boards/xtensa/esp32/esp32_defconfig b/boards/xtensa/esp32/esp32_defconfig index be5595cfe9..5d9839f049 100644 --- a/boards/xtensa/esp32/esp32_defconfig +++ b/boards/xtensa/esp32/esp32_defconfig @@ -31,3 +31,4 @@ CONFIG_I2C_0=y CONFIG_I2C_1=y CONFIG_I2C_2=n CONFIG_I2C_3=n +CONFIG_CLOCK_CONTROL=y diff --git a/drivers/clock_control/CMakeLists.txt b/drivers/clock_control/CMakeLists.txt index 37d4a7c360..7755a7b293 100644 --- a/drivers/clock_control/CMakeLists.txt +++ b/drivers/clock_control/CMakeLists.txt @@ -9,6 +9,7 @@ zephyr_sources_ifdef(CONFIG_CLOCK_CONTROL_MCUX_SIM clock_control_mcux zephyr_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF nrf_power_clock.c) zephyr_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION nrf_clock_calibration.c) zephyr_sources_ifdef(CONFIG_CLOCK_CONTROL_RV32M1_PCC clock_control_rv32m1_pcc.c) +zephyr_sources_ifdef(CONFIG_CLOCK_CONTROL_ESP32 clock_control_esp32.c) if(CONFIG_CLOCK_CONTROL_STM32_CUBE) if(CONFIG_SOC_SERIES_STM32MP1X) diff --git a/drivers/clock_control/Kconfig b/drivers/clock_control/Kconfig index 3cbe388d1d..66e3e08457 100644 --- a/drivers/clock_control/Kconfig +++ b/drivers/clock_control/Kconfig @@ -38,4 +38,6 @@ source "drivers/clock_control/Kconfig.mcux_sim" source "drivers/clock_control/Kconfig.rv32m1" +source "drivers/clock_control/Kconfig.esp32" + endif # CLOCK_CONTROL diff --git a/drivers/clock_control/Kconfig.esp32 b/drivers/clock_control/Kconfig.esp32 new file mode 100644 index 0000000000..9dc77aa24b --- /dev/null +++ b/drivers/clock_control/Kconfig.esp32 @@ -0,0 +1,10 @@ +# ESP32 Clock Driver configuration options + +# Copyright (c) 2020 Mohamed ElShahawi +# SPDX-License-Identifier: Apache-2.0 + +config CLOCK_CONTROL_ESP32 + bool "ESP32 Clock driver" + depends on SOC_ESP32 + help + Enable support for ESP32 clock driver. diff --git a/drivers/clock_control/clock_control_esp32.c b/drivers/clock_control/clock_control_esp32.c new file mode 100644 index 0000000000..a3ad34cdc8 --- /dev/null +++ b/drivers/clock_control/clock_control_esp32.c @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2020 Mohamed ElShahawi. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT espressif_esp32_rtc + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "clock_control_esp32.h" + +struct esp32_clock_config { + uint32_t clk_src_sel; + uint32_t cpu_freq; + uint32_t xtal_freq_sel; + uint32_t xtal_div; +}; + +struct control_regs { + /** Peripheral control register */ + uint32_t clk; + /** Peripheral reset register */ + uint32_t rst; +}; + +struct bbpll_cfg { + uint8_t div_ref; + uint8_t div7_0; + uint8_t div10_8; + uint8_t lref; + uint8_t dcur; + uint8_t bw; +}; + +struct pll_cfg { + uint8_t dbias_wak; + uint8_t endiv5; + uint8_t bbadc_dsmp; + struct bbpll_cfg bbpll[2]; +}; + + +#define PLL_APB_CLK_FREQ 80 + +#define RTC_PLL_FREQ_320M 0 +#define RTC_PLL_FREQ_480M 1 + +#define DPORT_CPUPERIOD_SEL_80 0 +#define DPORT_CPUPERIOD_SEL_160 1 +#define DPORT_CPUPERIOD_SEL_240 2 + +#define DEV_CFG(dev) ((struct esp32_clock_config *)(dev->config_info)) +#define GET_REG_BANK(module_id) ((uint32_t)module_id / 32U) +#define GET_REG_OFFSET(module_id) ((uint32_t)module_id % 32U) + +#define CLOCK_REGS_BANK_COUNT 3 + +const struct control_regs clock_control_regs[CLOCK_REGS_BANK_COUNT] = { + [0] = { .clk = DPORT_PERIP_CLK_EN_REG, .rst = DPORT_PERIP_RST_EN_REG }, + [1] = { .clk = DPORT_PERI_CLK_EN_REG, .rst = DPORT_PERI_RST_EN_REG }, + [2] = { .clk = DPORT_WIFI_CLK_EN_REG, .rst = DPORT_CORE_RST_EN_REG } +}; + +static uint32_t const xtal_freq[] = { + [ESP32_CLK_XTAL_40M] = 40, + [ESP32_CLK_XTAL_26M] = 26 +}; + +const struct pll_cfg pll_config[] = { + [RTC_PLL_FREQ_320M] = { + .dbias_wak = 0, + .endiv5 = BBPLL_ENDIV5_VAL_320M, + .bbadc_dsmp = BBPLL_BBADC_DSMP_VAL_320M, + .bbpll[ESP32_CLK_XTAL_40M] = { + /* 40mhz */ + .div_ref = 0, + .div7_0 = 32, + .div10_8 = 0, + .lref = 0, + .dcur = 6, + .bw = 3, + }, + .bbpll[ESP32_CLK_XTAL_26M] = { + /* 26mhz */ + .div_ref = 12, + .div7_0 = 224, + .div10_8 = 4, + .lref = 1, + .dcur = 0, + .bw = 1, + } + }, + [RTC_PLL_FREQ_480M] = { + .dbias_wak = 0, + .endiv5 = BBPLL_ENDIV5_VAL_480M, + .bbadc_dsmp = BBPLL_BBADC_DSMP_VAL_480M, + .bbpll[ESP32_CLK_XTAL_40M] = { + /* 40mhz */ + .div_ref = 0, + .div7_0 = 28, + .div10_8 = 0, + .lref = 0, + .dcur = 6, + .bw = 3, + }, + .bbpll[ESP32_CLK_XTAL_26M] = { + /* 26mhz */ + .div_ref = 12, + .div7_0 = 144, + .div10_8 = 4, + .lref = 1, + .dcur = 0, + .bw = 1, + } + } +}; + +static void bbpll_configure(rtc_xtal_freq_t xtal_freq, uint32_t pll_freq) +{ + uint8_t dbias_wak = 0; + + const struct pll_cfg *cfg = &pll_config[pll_freq]; + const struct bbpll_cfg *bb_cfg = &pll_config[pll_freq].bbpll[xtal_freq]; + + /* Enable PLL, Clear PowerDown (_PD) flags */ + CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, + RTC_CNTL_BIAS_I2C_FORCE_PD | + RTC_CNTL_BB_I2C_FORCE_PD | + RTC_CNTL_BBPLL_FORCE_PD | + RTC_CNTL_BBPLL_I2C_FORCE_PD); + + /* reset BBPLL configuration */ + I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_IR_CAL_DELAY, BBPLL_IR_CAL_DELAY_VAL); + I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_IR_CAL_EXT_CAP, BBPLL_IR_CAL_EXT_CAP_VAL); + I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_ENB_FCAL, BBPLL_OC_ENB_FCAL_VAL); + I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_ENB_VCON, BBPLL_OC_ENB_VCON_VAL); + I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_BBADC_CAL_7_0, BBPLL_BBADC_CAL_7_0_VAL); + + /* voltage needs to be changed for CPU@240MHz or + * 80MHz Flash (because of internal flash regulator) + */ + if (pll_freq == RTC_PLL_FREQ_320M) { + dbias_wak = DIG_DBIAS_80M_160M; + } else { /* RTC_PLL_FREQ_480M */ + dbias_wak = DIG_DBIAS_240M; + } + + /* Configure the voltage */ + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, dbias_wak); + + I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_ENDIV5, cfg->endiv5); + I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_BBADC_DSMP, cfg->bbadc_dsmp); + + uint8_t i2c_bbpll_lref = (bb_cfg->lref << 7) | (bb_cfg->div10_8 << 4) | (bb_cfg->div_ref); + + I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_LREF, i2c_bbpll_lref); + I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, bb_cfg->div7_0); + I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_DCUR, ((bb_cfg->bw << 6) | bb_cfg->dcur)); +} + +static void cpuclk_pll_configure(uint32_t xtal_freq, uint32_t cpu_freq) +{ + uint32_t pll_freq = RTC_PLL_FREQ_320M; + uint32_t cpu_period_sel = DPORT_CPUPERIOD_SEL_80; + + switch (cpu_freq) { + case ESP32_CLK_CPU_80M: + pll_freq = RTC_PLL_FREQ_320M; + cpu_period_sel = DPORT_CPUPERIOD_SEL_80; + break; + case ESP32_CLK_CPU_160M: + pll_freq = RTC_PLL_FREQ_320M; + cpu_period_sel = DPORT_CPUPERIOD_SEL_160; + break; + case ESP32_CLK_CPU_240M: + pll_freq = RTC_PLL_FREQ_480M; + cpu_period_sel = DPORT_CPUPERIOD_SEL_240; + break; + } + + /* Configure PLL based on XTAL Value */ + bbpll_configure(xtal_freq, pll_freq); + /* Set CPU Speed (80,160,240) */ + DPORT_REG_WRITE(DPORT_CPU_PER_CONF_REG, cpu_period_sel); + /* Set PLL as CPU Clock Source */ + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, RTC_CNTL_SOC_CLK_SEL_PLL); + + /* + * Update REF_Tick, + * if PLL is the cpu clock source, APB frequency is always 80MHz + */ + REG_WRITE(APB_CTRL_PLL_TICK_CONF_REG, PLL_APB_CLK_FREQ - 1); +} + +static int clock_control_esp32_on(struct device *dev, + clock_control_subsys_t sys) +{ + ARG_UNUSED(dev); + uint32_t bank = GET_REG_BANK(sys); + uint32_t offset = GET_REG_OFFSET(sys); + + __ASSERT_NO_MSG(bank >= CLOCK_REGS_BANK_COUNT); + + esp32_set_mask32(BIT(offset), clock_control_regs[bank].clk); + esp32_clear_mask32(BIT(offset), clock_control_regs[bank].rst); + return 0; +} + +static int clock_control_esp32_off(struct device *dev, + clock_control_subsys_t sys) +{ + ARG_UNUSED(dev); + uint32_t bank = GET_REG_BANK(sys); + uint32_t offset = GET_REG_OFFSET(sys); + + __ASSERT_NO_MSG(bank >= CLOCK_REGS_BANK_COUNT); + + esp32_clear_mask32(BIT(offset), clock_control_regs[bank].clk); + esp32_set_mask32(BIT(offset), clock_control_regs[bank].rst); + return 0; +} + +static enum clock_control_status clock_control_esp32_get_status(struct device *dev, + clock_control_subsys_t sys) +{ + ARG_UNUSED(dev); + uint32_t bank = GET_REG_BANK(sys); + uint32_t offset = GET_REG_OFFSET(sys); + + if (DPORT_GET_PERI_REG_MASK(clock_control_regs[bank].clk, BIT(offset))) { + return CLOCK_CONTROL_STATUS_ON; + } + return CLOCK_CONTROL_STATUS_OFF; +} + +static int clock_control_esp32_get_rate(struct device *dev, + clock_control_subsys_t sub_system, + uint32_t *rate) +{ + ARG_UNUSED(sub_system); + + uint32_t xtal_freq_sel = DEV_CFG(dev)->xtal_freq_sel; + uint32_t soc_clk_sel = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL); + + switch (soc_clk_sel) { + case RTC_CNTL_SOC_CLK_SEL_XTL: + *rate = xtal_freq[xtal_freq_sel]; + return 0; + case RTC_CNTL_SOC_CLK_SEL_PLL: + *rate = MHZ(80); + return 0; + default: + *rate = 0; + return -ENOTSUP; + } +} + +static int clock_control_esp32_init(struct device *dev) +{ + struct esp32_clock_config *cfg = DEV_CFG(dev); + + /* Wait for UART first before changing freq to avoid garbage on console */ + esp32_rom_uart_tx_wait_idle(0); + + switch (cfg->clk_src_sel) { + case ESP32_CLK_SRC_XTAL: + REG_SET_FIELD(APB_CTRL_SYSCLK_CONF_REG, APB_CTRL_PRE_DIV_CNT, cfg->xtal_div); + /* adjust ref_tick */ + REG_WRITE(APB_CTRL_XTAL_TICK_CONF_REG, xtal_freq[cfg->xtal_freq_sel] - 1); + /* switch clock source */ + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, RTC_CNTL_SOC_CLK_SEL_XTL); + break; + case ESP32_CLK_SRC_PLL: + cpuclk_pll_configure(cfg->xtal_freq_sel, cfg->cpu_freq); + break; + default: + return -EINVAL; + } + + /* Re-calculate the CCOUNT register value to make time calculation correct. + * This should be updated on each frequency change + * New CCOUNT = Current CCOUNT * (new freq / old freq) + */ + XTHAL_SET_CCOUNT((uint64_t)XTHAL_GET_CCOUNT() * cfg->cpu_freq / xtal_freq[cfg->xtal_freq_sel]); + return 0; +} + +static const struct clock_control_driver_api clock_control_esp32_api = { + .on = clock_control_esp32_on, + .off = clock_control_esp32_off, + .get_rate = clock_control_esp32_get_rate, + .get_status = clock_control_esp32_get_status, +}; + +static const struct esp32_clock_config esp32_clock_config0 = { + .clk_src_sel = DT_PROP(DT_INST(0, cadence_tensilica_xtensa_lx6), clock_source), + .cpu_freq = DT_PROP(DT_INST(0, cadence_tensilica_xtensa_lx6), clock_frequency), + .xtal_freq_sel = DT_INST_PROP(0, xtal_freq), + .xtal_div = DT_INST_PROP(0, xtal_div), +}; + +DEVICE_AND_API_INIT(clk_esp32, DT_INST_LABEL(0), + &clock_control_esp32_init, + NULL, &esp32_clock_config0, + PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS, + &clock_control_esp32_api); + +BUILD_ASSERT((CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC) == MHZ(DT_PROP(DT_INST(0, cadence_tensilica_xtensa_lx6), clock_frequency)), + "SYS_CLOCK_HW_CYCLES_PER_SEC Value must be equal to CPU_Freq"); + +BUILD_ASSERT(DT_NODE_HAS_PROP(DT_INST(0, cadence_tensilica_xtensa_lx6), clock_source), + "CPU clock-source property must be set to ESP32_CLK_SRC_XTAL or ESP32_CLK_SRC_PLL"); diff --git a/drivers/clock_control/clock_control_esp32.h b/drivers/clock_control/clock_control_esp32.h new file mode 100644 index 0000000000..279a619c43 --- /dev/null +++ b/drivers/clock_control/clock_control_esp32.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2020 Mohamed ElShahawi. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_CLOCK_CONTROL_ESP32_CLOCK_H_ +#define ZEPHYR_DRIVERS_CLOCK_CONTROL_ESP32_CLOCK_H_ + +#include + +/* + * Convenience macros for the above functions. + */ +#define I2C_WRITEREG_RTC(block, reg_add, indata) \ + esp32_rom_i2c_writeReg(block, block##_HOSTID, reg_add, indata) + +#define I2C_READREG_RTC(block, reg_add) \ + esp32_rom_i2c_readReg(block, block##_HOSTID, reg_add) + + +# define XTHAL_GET_CCOUNT() ({ int __ccount; \ + __asm__ __volatile__ ("rsr.ccount %0" : "=a" (__ccount)); \ + __ccount; }) + +# define XTHAL_SET_CCOUNT(v) do { int __ccount = (int)(v); \ + __asm__ __volatile__ ("wsr.ccount %0" : : "a" (__ccount) : "memory"); \ + } while (0) + +/* + * Get voltage level for CPU to run at 240 MHz, or for flash/PSRAM to run at 80 MHz. + * 0x0: level 7; 0x1: level 6; 0x2: level 5; 0x3: level 4. (RO) + */ +#define GET_HP_VOLTAGE (RTC_CNTL_DBIAS_1V25 - ((EFUSE_BLK0_RDATA5_REG >> 22) & 0x3)) +#define DIG_DBIAS_240M GET_HP_VOLTAGE +#define DIG_DBIAS_80M_160M RTC_CNTL_DBIAS_1V10 /* FIXME: This macro should be GET_HP_VOLTAGE in case of 80Mhz flash frequency */ +#define DIG_DBIAS_XTAL RTC_CNTL_DBIAS_1V10 + +/** + * Register definitions for digital PLL (BBPLL) + * This file lists register fields of BBPLL, located on an internal configuration + * bus. + */ +#define I2C_BBPLL 0x66 +#define I2C_BBPLL_HOSTID 4 +#define I2C_BBPLL_IR_CAL_DELAY 0 +#define I2C_BBPLL_IR_CAL_EXT_CAP 1 +#define I2C_BBPLL_OC_LREF 2 +#define I2C_BBPLL_OC_DIV_7_0 3 +#define I2C_BBPLL_OC_ENB_FCAL 4 +#define I2C_BBPLL_OC_DCUR 5 +#define I2C_BBPLL_BBADC_DSMP 9 +#define I2C_BBPLL_OC_ENB_VCON 10 +#define I2C_BBPLL_ENDIV5 11 +#define I2C_BBPLL_BBADC_CAL_7_0 12 + +/* BBPLL configuration values */ +#define BBPLL_ENDIV5_VAL_320M 0x43 +#define BBPLL_BBADC_DSMP_VAL_320M 0x84 +#define BBPLL_ENDIV5_VAL_480M 0xc3 +#define BBPLL_BBADC_DSMP_VAL_480M 0x74 +#define BBPLL_IR_CAL_DELAY_VAL 0x18 +#define BBPLL_IR_CAL_EXT_CAP_VAL 0x20 +#define BBPLL_OC_ENB_FCAL_VAL 0x9a +#define BBPLL_OC_ENB_VCON_VAL 0x00 +#define BBPLL_BBADC_CAL_7_0_VAL 0x00 + +#endif /* ZEPHYR_DRIVERS_CLOCK_CONTROL_ESP32_CLOCK_H_ */ diff --git a/dts/bindings/clock/espressif,esp32-rtc.yaml b/dts/bindings/clock/espressif,esp32-rtc.yaml new file mode 100644 index 0000000000..9212072b94 --- /dev/null +++ b/dts/bindings/clock/espressif,esp32-rtc.yaml @@ -0,0 +1,31 @@ +# Copyright (c) 2020, Mohamed ElShahawi +# SPDX-License-Identifier: Apache-2.0 + +description: ESP32 RTC (Power & Clock Controller Module) Module + +compatible: "espressif,esp32-rtc" + +include: [clock-controller.yaml, base.yaml] + +properties: + reg: + required: true + + label: + required: true + + xtal-freq: + type: int + required: true + description: Value of the extrernal XTAL connected to ESP32, Supported values 40M,26M + + xtal-div: + type: int + required: true + description: Divisor value for XTAL Clock, CPU_CLK = XTAL_FREQ / xtal-div + + "#clock-cells": + const: 1 + +clock-cells: + - offset # Index of the peripheral in esp32 modules list (Check esp32_clock.h) diff --git a/dts/bindings/cpu/cadence,tensilica-xtensa-lx6.yaml b/dts/bindings/cpu/cadence,tensilica-xtensa-lx6.yaml index ee116aba81..8fe80f6483 100644 --- a/dts/bindings/cpu/cadence,tensilica-xtensa-lx6.yaml +++ b/dts/bindings/cpu/cadence,tensilica-xtensa-lx6.yaml @@ -6,3 +6,9 @@ description: Cadence Tensilica Xtensa LX6 CPU compatible: "cadence,tensilica-xtensa-lx6" include: cpu.yaml + +properties: + clock-source: + type: int + description: cpu clock source + required: false diff --git a/dts/xtensa/espressif/esp32.dtsi b/dts/xtensa/espressif/esp32.dtsi index 1d7b75fc46..d530023e9b 100644 --- a/dts/xtensa/espressif/esp32.dtsi +++ b/dts/xtensa/espressif/esp32.dtsi @@ -6,6 +6,7 @@ #include #include #include +#include / { chosen { @@ -20,12 +21,14 @@ device_type = "cpu"; compatible = "cadence,tensilica-xtensa-lx6"; reg = <0>; + clock-source = ; }; cpu1: cpu@1 { device_type = "cpu"; compatible = "cadence,tensilica-xtensa-lx6"; reg = <1>; + clock-source = ; }; }; @@ -36,6 +39,16 @@ reg = <0x3FFB0000 0x50000>; }; + rtc: rtc@3ff48000 { + compatible = "espressif,esp32-rtc"; + reg = <0x3ff48000 0x0D8>; + label = "RTC"; + xtal-freq = ; + xtal-div = <0>; + #clock-cells = <1>; + status = "ok"; + }; + soc { uart0: uart@3ff40000 { compatible = "espressif,esp32-uart"; diff --git a/include/dt-bindings/clock/esp32_clock.h b/include/dt-bindings/clock/esp32_clock.h new file mode 100644 index 0000000000..bcf1f11985 --- /dev/null +++ b/include/dt-bindings/clock/esp32_clock.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2020 Mohamed ElShahawi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32_H_ + +/* System Clock Source */ +#define ESP32_CLK_SRC_XTAL 0U +#define ESP32_CLK_SRC_PLL 1U +#define ESP32_CLK_SRC_RTC8M 2U + +/* Supported CPU Frequencies */ +#define ESP32_CLK_CPU_26M 26U +#define ESP32_CLK_CPU_40M 40U +#define ESP32_CLK_CPU_80M 80U +#define ESP32_CLK_CPU_160M 160U +#define ESP32_CLK_CPU_240M 240U + +/* Supported XTAL Frequencies */ +#define ESP32_CLK_XTAL_40M 0U +#define ESP32_CLK_XTAL_26M 1U + +/* Modules IDs + * These IDs are actually offsets in CLK and RST Control registers. + * These IDs shouldn't be changed unless there is a Hardware change + * from Espressif. + * + * Basic Modules + * Registers: DPORT_PERIP_CLK_EN_REG, DPORT_PERIP_RST_EN_REG + */ +#define ESP32_TIMERS_MODULE 0 +#define ESP32_SPI1_MODULE 1 +#define ESP32_UART0_MODULE 2 +#define ESP32_WDG_MODULE 3 +#define ESP32_I2S0_MODULE 4 +#define ESP32_UART1_MODULE 5 +#define ESP32_SPI2_MODULE 6 +#define ESP32_I2C_EXT0_MODULE 7 +#define ESP32_UHCI0_MODULE 8 +#define ESP32_RMT_MODULE 9 +#define ESP32_PCNT_MODULE 10 +#define ESP32_LEDC_MODULE 11 +#define ESP32_UHCI1_MODULE 12 +#define ESP32_TIMERGROUP_MODULE 13 +#define ESP32_EFUSE_MODULE 14 +#define ESP32_TIMERGROUP1_MODULE 15 +#define ESP32_SPI3_MODULE 16 +#define ESP32_PWM0_MODULE 17 +#define ESP32_I2C_EXT1_MODULE 18 +#define ESP32_CAN_MODULE 19 +#define ESP32_PWM1_MODULE 20 +#define ESP32_I2S1_MODULE 21 +#define ESP32_SPI_DMA_MODULE 22 +#define ESP32_UART2_MODULE 23 +#define ESP32_UART_MEM_MODULE 24 +#define ESP32_PWM2_MODULE 25 +#define ESP32_PWM3_MODULE 26 + +/* HW Security Modules + * Registers: DPORT_PERI_CLK_EN_REG, DPORT_PERI_RST_EN_REG + */ +#define ESP32_AES_MODULE 32 +#define ESP32_SHA_MODULE 33 +#define ESP32_RSA_MODULE 34 +#define ESP32_SECUREBOOT_MODULE 35 /* Secure boot reset will hold SHA & AES in reset */ +#define ESP32_DIGITAL_SIGNATURE_MODULE 36 /* Digital signature reset will hold AES & RSA in reset */ + +/* WiFi/BT + * Registers: DPORT_WIFI_CLK_EN_REG, DPORT_CORE_RST_EN_REG + */ +#define ESP32_SDMMC_MODULE 64 +#define ESP32_SDIO_SLAVE_MODULE 65 +#define ESP32_EMAC_MODULE 66 +#define ESP32_RNG_MODULE 67 +#define ESP32_WIFI_MODULE 68 +#define ESP32_BT_MODULE 69 +#define ESP32_WIFI_BT_COMMON_MODULE 70 +#define ESP32_BT_BASEBAND_MODULE 71 +#define ESP32_BT_LC_MODULE 72 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32_H_ */ diff --git a/soc/xtensa/esp32/Kconfig.soc b/soc/xtensa/esp32/Kconfig.soc index 8da147b6f7..e232841bd6 100644 --- a/soc/xtensa/esp32/Kconfig.soc +++ b/soc/xtensa/esp32/Kconfig.soc @@ -4,3 +4,5 @@ config SOC_ESP32 bool "ESP32" select XTENSA + select CLOCK_CONTROL + select CLOCK_CONTROL_ESP32 diff --git a/soc/xtensa/esp32/linker.ld b/soc/xtensa/esp32/linker.ld index e01fb03e52..7a23360ce9 100644 --- a/soc/xtensa/esp32/linker.ld +++ b/soc/xtensa/esp32/linker.ld @@ -25,12 +25,15 @@ PROVIDE ( __stack = 0x3ffe3f20 ); PROVIDE ( esp32_rom_uart_tx_one_char = 0x40009200 ); PROVIDE ( esp32_rom_uart_rx_one_char = 0x400092d0 ); PROVIDE ( esp32_rom_uart_attach = 0x40008fd0 ); +PROVIDE ( esp32_rom_uart_tx_wait_idle = 0x40009278 ); PROVIDE ( esp32_rom_intr_matrix_set = 0x4000681c ); PROVIDE ( esp32_rom_gpio_matrix_in = 0x40009edc ); PROVIDE ( esp32_rom_gpio_matrix_out = 0x40009f0c ); PROVIDE ( esp32_rom_Cache_Flush = 0x40009a14 ); PROVIDE ( esp32_rom_Cache_Read_Enable = 0x40009a84 ); PROVIDE ( esp32_rom_ets_set_appcpu_boot_addr = 0x4000689c ); +PROVIDE ( esp32_rom_i2c_readReg = 0x40004148 ); +PROVIDE ( esp32_rom_i2c_writeReg = 0x400041a4 ); MEMORY { diff --git a/soc/xtensa/esp32/soc.h b/soc/xtensa/esp32/soc.h index f1c6ab1742..d1cdb3957f 100644 --- a/soc/xtensa/esp32/soc.h +++ b/soc/xtensa/esp32/soc.h @@ -52,6 +52,7 @@ extern int esp32_rom_gpio_matrix_out(uint32_t gpio, uint32_t signal_index, bool out_enabled_inverted); extern void esp32_rom_uart_attach(void); +extern void esp32_rom_uart_tx_wait_idle(uint8_t uart_no); extern STATUS esp32_rom_uart_tx_one_char(uint8_t chr); extern STATUS esp32_rom_uart_rx_one_char(uint8_t *chr); @@ -59,4 +60,8 @@ extern void esp32_rom_Cache_Flush(int cpu); extern void esp32_rom_Cache_Read_Enable(int cpu); extern void esp32_rom_ets_set_appcpu_boot_addr(void *addr); +/* ROM functions which read/write internal i2c control bus for PLL, APLL */ +extern uint8_t esp32_rom_i2c_readReg(uint8_t block, uint8_t host_id, uint8_t reg_add); +extern void esp32_rom_i2c_writeReg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data); + #endif /* __SOC_H__ */