From f9e0fa9af349590d29b28ea7cfc01538a363eff4 Mon Sep 17 00:00:00 2001 From: Mohamed ElShahawi Date: Thu, 28 May 2020 21:01:49 +0200 Subject: [PATCH] drivers: esp32/clock_control: support UART, I2C - Change default CPU Clock to 240MHz (PLL is activated) - I2C, UART will use sysclk from clock driver - esp32_enable_peripheral replaced by clock_control_on Signed-off-by: Mohamed ElShahawi --- boards/xtensa/esp32/esp32.dts | 4 +-- boards/xtensa/esp32/esp32_defconfig | 2 +- drivers/i2c/i2c_esp32.c | 39 +++++++++++++++++++---------- drivers/serial/uart_esp32.c | 36 +++++++++++++++++--------- dts/xtensa/espressif/esp32.dtsi | 9 +++++-- soc/xtensa/esp32/soc.h | 17 ------------- 6 files changed, 60 insertions(+), 47 deletions(-) diff --git a/boards/xtensa/esp32/esp32.dts b/boards/xtensa/esp32/esp32.dts index 9084426b77a..4e9c0bfe2ba 100644 --- a/boards/xtensa/esp32/esp32.dts +++ b/boards/xtensa/esp32/esp32.dts @@ -24,11 +24,11 @@ }; &cpu0 { - clock-frequency = ; + clock-frequency = ; }; &cpu1 { - clock-frequency = ; + clock-frequency = ; }; &uart0 { diff --git a/boards/xtensa/esp32/esp32_defconfig b/boards/xtensa/esp32/esp32_defconfig index 5d9839f049b..9d7f4193326 100644 --- a/boards/xtensa/esp32/esp32_defconfig +++ b/boards/xtensa/esp32/esp32_defconfig @@ -7,7 +7,7 @@ CONFIG_SOC_ESP32=y CONFIG_MAIN_STACK_SIZE=2048 -CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=40000000 +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=240000000 CONFIG_CONSOLE=y CONFIG_SERIAL=y diff --git a/drivers/i2c/i2c_esp32.c b/drivers/i2c/i2c_esp32.c index a3cd90e0683..ca9af8574ef 100644 --- a/drivers/i2c/i2c_esp32.c +++ b/drivers/i2c/i2c_esp32.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -61,6 +62,7 @@ struct i2c_esp32_data { struct k_sem fifo_sem; struct k_sem transfer_sem; + struct device *clock_dev; }; typedef void (*irq_connect_cb)(void); @@ -69,6 +71,7 @@ struct i2c_esp32_config { int index; irq_connect_cb connect_irq; + const char *clock_name; const struct { int sda_out; @@ -82,7 +85,7 @@ struct i2c_esp32_config { int sda; } pins; - const struct esp32_peripheral peripheral; + const clock_control_subsys_t peripheral_id; const struct { bool tx_lsb_first; @@ -126,7 +129,7 @@ static int i2c_esp32_configure_pins(int pin, int matrix_out, int matrix_in) return 0; } -static int i2c_esp32_configure_speed(const struct i2c_esp32_config *config, +static int i2c_esp32_configure_speed(struct device *dev, uint32_t speed) { static const uint32_t speed_to_freq_tbl[] = { @@ -136,6 +139,11 @@ static int i2c_esp32_configure_speed(const struct i2c_esp32_config *config, [I2C_SPEED_HIGH] = 0, [I2C_SPEED_ULTRA] = 0 }; + + const struct i2c_esp32_config *config = dev->config_info; + struct i2c_esp32_data *data = dev->driver_data; + + uint32_t sys_clk_freq = 0; uint32_t freq_hz = speed_to_freq_tbl[speed]; uint32_t period; @@ -143,8 +151,13 @@ static int i2c_esp32_configure_speed(const struct i2c_esp32_config *config, return -ENOTSUP; } - period = (APB_CLK_FREQ / freq_hz); + if (clock_control_get_rate(data->clock_dev, + config->peripheral_id, + &sys_clk_freq)) { + return -EINVAL; + } + period = (sys_clk_freq / freq_hz); period /= 2U; /* Set hold and setup times to 1/2th of period */ esp32_set_mask32(period << I2C_SCL_LOW_PERIOD_S, @@ -192,7 +205,7 @@ static int i2c_esp32_configure(struct device *dev, uint32_t dev_config) return ret; } - esp32_enable_peripheral(&config->peripheral); + clock_control_on(data->clock_dev, config->peripheral_id); /* MSB or LSB first is configurable for both TX and RX */ if (config->mode.tx_lsb_first) { @@ -228,7 +241,7 @@ static int i2c_esp32_configure(struct device *dev, uint32_t dev_config) v |= I2C_CLK_EN; sys_write32(v, I2C_CTR_REG(config->index)); - ret = i2c_esp32_configure_speed(config, I2C_SPEED_GET(dev_config)); + ret = i2c_esp32_configure_speed(dev, I2C_SPEED_GET(dev_config)); if (ret < 0) { goto out; } @@ -578,6 +591,8 @@ static void i2c_esp32_connect_irq_0(void) static const struct i2c_esp32_config i2c_esp32_config_0 = { .index = 0, .connect_irq = i2c_esp32_connect_irq_0, + .clock_name = DT_INST_CLOCKS_LABEL(0), + .peripheral_id = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(0, offset), .sig = { .sda_out = I2CEXT0_SDA_OUT_IDX, .sda_in = I2CEXT0_SDA_IN_IDX, @@ -588,10 +603,6 @@ static const struct i2c_esp32_config i2c_esp32_config_0 = { .scl = DT_INST_PROP(0, scl_pin), .sda = DT_INST_PROP(0, sda_pin), }, - .peripheral = { - .clk = DPORT_I2C_EXT0_CLK_EN, - .rst = DPORT_I2C_EXT0_RST, - }, .mode = { .tx_lsb_first = IS_ENABLED(CONFIG_I2C_ESP32_0_TX_LSB_FIRST), @@ -626,6 +637,8 @@ static void i2c_esp32_connect_irq_1(void) static const struct i2c_esp32_config i2c_esp32_config_1 = { .index = 1, .connect_irq = i2c_esp32_connect_irq_1, + .clock_name = DT_INST_CLOCKS_LABEL(1), + .peripheral_id = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(1, offset), .sig = { .sda_out = I2CEXT1_SDA_OUT_IDX, .sda_in = I2CEXT1_SDA_IN_IDX, @@ -636,10 +649,6 @@ static const struct i2c_esp32_config i2c_esp32_config_1 = { .scl = DT_INST_PROP(1, scl_pin), .sda = DT_INST_PROP(1, sda_pin), }, - .peripheral = { - .clk = DPORT_I2C_EXT1_CLK_EN, - .rst = DPORT_I2C_EXT1_RST, - }, .mode = { .tx_lsb_first = IS_ENABLED(CONFIG_I2C_ESP32_1_TX_LSB_FIRST), @@ -667,6 +676,10 @@ static int i2c_esp32_init(struct device *dev) const struct i2c_esp32_config *config = dev->config_info; struct i2c_esp32_data *data = dev->driver_data; uint32_t bitrate_cfg = i2c_map_dt_bitrate(config->bitrate); + data->clock_dev = device_get_binding(config->clock_name); + + __ASSERT_NO_MSG(data->clock_dev); + unsigned int key = irq_lock(); k_sem_init(&data->fifo_sem, 1, 1); diff --git a/drivers/serial/uart_esp32.c b/drivers/serial/uart_esp32.c index e01fb99816a..0d55040f7b3 100644 --- a/drivers/serial/uart_esp32.c +++ b/drivers/serial/uart_esp32.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -62,6 +63,7 @@ struct uart_esp32_regs_t { struct uart_esp32_config { struct uart_device_config dev_conf; + const char *clock_name; const struct { int tx_out; @@ -77,7 +79,7 @@ struct uart_esp32_config { int cts; } pins; - const struct esp32_peripheral peripheral; + const clock_control_subsys_t peripheral_id; const struct { int source; @@ -88,6 +90,7 @@ struct uart_esp32_config { /* driver data */ struct uart_esp32_data { struct uart_config uart_config; + struct device *clock_dev; #ifdef CONFIG_UART_INTERRUPT_DRIVEN uart_irq_callback_user_data_t irq_cb; void *irq_cb_data; @@ -185,7 +188,14 @@ static int uart_esp32_config_get(struct device *dev, struct uart_config *cfg) static int uart_esp32_set_baudrate(struct device *dev, int baudrate) { - uint32_t sys_clk_freq = DEV_CFG(dev)->dev_conf.sys_clk_freq; + uint32_t sys_clk_freq = 0; + + if (clock_control_get_rate(DEV_DATA(dev)->clock_dev, + DEV_CFG(dev)->peripheral_id, + &sys_clk_freq)) { + return -EINVAL; + } + uint32_t clk_div = (((sys_clk_freq) << 4) / baudrate); while (UART_TXFIFO_COUNT(DEV_BASE(dev)->status)) { @@ -237,7 +247,7 @@ static int uart_esp32_configure(struct device *dev, | (UART_TX_FIFO_THRESH << UART_TXFIFO_EMPTY_THRHD_S); uart_esp32_configure_pins(dev); - esp32_enable_peripheral(&DEV_CFG(dev)->peripheral); + clock_control_on(DEV_DATA(dev)->clock_dev, DEV_CFG(dev)->peripheral_id); /* * Reset RX Buffer by reading all received bytes @@ -305,6 +315,12 @@ static int uart_esp32_configure(struct device *dev, static int uart_esp32_init(struct device *dev) { + struct uart_esp32_data *data = DEV_DATA(dev); + + data->clock_dev = device_get_binding(DEV_CFG(dev)->clock_name); + + __ASSERT_NO_MSG(data->clock_dev); + uart_esp32_configure(dev, &DEV_DATA(dev)->uart_config); #ifdef CONFIG_UART_INTERRUPT_DRIVEN @@ -483,16 +499,11 @@ static const struct uart_esp32_config uart_esp32_cfg_port_##idx = { \ .dev_conf = { \ .base = \ (uint8_t *)DT_INST_REG_ADDR(idx), \ - .sys_clk_freq = \ - DT_PROP(DT_INST(0, cadence_tensilica_xtensa_lx6), clock_frequency),\ ESP32_UART_IRQ_HANDLER_FUNC(idx) \ }, \ - \ - .peripheral = { \ - .clk = DPORT_UART##idx##_CLK_EN, \ - .rst = DPORT_UART##idx##_RST, \ - }, \ - \ + \ + .clock_name = DT_INST_CLOCKS_LABEL(idx), \ + \ .signals = { \ .tx_out = U##idx##TXD_OUT_IDX, \ .rx_in = U##idx##RXD_IN_IDX, \ @@ -509,7 +520,8 @@ static const struct uart_esp32_config uart_esp32_cfg_port_##idx = { \ .cts = DT_INST_PROP(idx, cts_pin), \ )) \ }, \ - \ + \ + .peripheral_id = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(idx, offset), \ .irq = { \ .source = ETS_UART##idx##_INTR_SOURCE, \ .line = INST_##idx##_ESPRESSIF_ESP32_UART_IRQ_0, \ diff --git a/dts/xtensa/espressif/esp32.dtsi b/dts/xtensa/espressif/esp32.dtsi index d530023e9b0..a784bb5310f 100644 --- a/dts/xtensa/espressif/esp32.dtsi +++ b/dts/xtensa/espressif/esp32.dtsi @@ -21,14 +21,14 @@ device_type = "cpu"; compatible = "cadence,tensilica-xtensa-lx6"; reg = <0>; - clock-source = ; + clock-source = ; }; cpu1: cpu@1 { device_type = "cpu"; compatible = "cadence,tensilica-xtensa-lx6"; reg = <1>; - clock-source = ; + clock-source = ; }; }; @@ -55,6 +55,7 @@ reg = <0x3ff40000 0x400>; /* interrupts = <12>; - FIXME: Enable interrupts when interrupt-controller got supported in device tree */ label = "UART_0"; + clocks = <&rtc ESP32_UART0_MODULE>; status = "disabled"; }; @@ -63,6 +64,7 @@ reg = <0x3ff50000 0x400>; /* interrupts = <17>; - FIXME: Enable interrupts when interrupt-controller got supported in device tree */ label = "UART_1"; + clocks = <&rtc ESP32_UART1_MODULE>; status = "disabled"; }; @@ -71,6 +73,7 @@ reg = <0x3ff6E000 0x400>; /* interrupts = <18>; - FIXME: Enable interrupts when interrupt-controller got supported in device tree */ label = "UART_2"; + clocks = <&rtc ESP32_UART2_MODULE>; status = "disabled"; }; @@ -104,6 +107,7 @@ reg = <0x3ff53000 0x1000>; /* interrupts = <8>; - FIXME: Enable interrupts when interrupt-controller got supported in device tree */ label = "I2C_0"; + clocks = <&rtc ESP32_I2C_EXT0_MODULE>; status = "disabled"; }; @@ -114,6 +118,7 @@ reg = <0x3ff67000 0x1000>; /* interrupts = <9>; - FIXME: Enable interrupts when interrupt-controller got supported in device tree */ label = "I2C_1"; + clocks = <&rtc ESP32_I2C_EXT1_MODULE>; status = "disabled"; }; diff --git a/soc/xtensa/esp32/soc.h b/soc/xtensa/esp32/soc.h index d1cdb3957fd..8c6fbc2eaaf 100644 --- a/soc/xtensa/esp32/soc.h +++ b/soc/xtensa/esp32/soc.h @@ -14,17 +14,6 @@ #include #include -/** - * @brief Struct to peripheral masks to enable peripheral - * clock and reset peripherals. - */ -struct esp32_peripheral { - /** Mask for clock peripheral */ - int clk; - /** Mask for reset peripheral */ - int rst; -}; - static inline void esp32_set_mask32(uint32_t v, uint32_t mem_addr) { sys_write32(sys_read32(mem_addr) | v, mem_addr); @@ -35,12 +24,6 @@ static inline void esp32_clear_mask32(uint32_t v, uint32_t mem_addr) sys_write32(sys_read32(mem_addr) & ~v, mem_addr); } -static inline void esp32_enable_peripheral(const struct esp32_peripheral *peripheral) -{ - esp32_set_mask32(peripheral->clk, DPORT_PERIP_CLK_EN_REG); - esp32_clear_mask32(peripheral->rst, DPORT_PERIP_RST_EN_REG); -} - extern int esp32_rom_intr_matrix_set(int cpu_no, int interrupt_src, int interrupt_line);