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 <ExtremeGTX@hotmail.com>
This commit is contained in:
Mohamed ElShahawi 2020-05-28 21:01:49 +02:00 committed by Kumar Gala
commit f9e0fa9af3
6 changed files with 60 additions and 47 deletions

View file

@ -24,11 +24,11 @@
}; };
&cpu0 { &cpu0 {
clock-frequency = <ESP32_CLK_CPU_40M>; clock-frequency = <ESP32_CLK_CPU_240M>;
}; };
&cpu1 { &cpu1 {
clock-frequency = <ESP32_CLK_CPU_40M>; clock-frequency = <ESP32_CLK_CPU_240M>;
}; };
&uart0 { &uart0 {

View file

@ -7,7 +7,7 @@ CONFIG_SOC_ESP32=y
CONFIG_MAIN_STACK_SIZE=2048 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_CONSOLE=y
CONFIG_SERIAL=y CONFIG_SERIAL=y

View file

@ -17,6 +17,7 @@
#include <drivers/gpio.h> #include <drivers/gpio.h>
#include <drivers/gpio/gpio_esp32.h> #include <drivers/gpio/gpio_esp32.h>
#include <drivers/i2c.h> #include <drivers/i2c.h>
#include <drivers/clock_control.h>
#include <sys/util.h> #include <sys/util.h>
#include <string.h> #include <string.h>
@ -61,6 +62,7 @@ struct i2c_esp32_data {
struct k_sem fifo_sem; struct k_sem fifo_sem;
struct k_sem transfer_sem; struct k_sem transfer_sem;
struct device *clock_dev;
}; };
typedef void (*irq_connect_cb)(void); typedef void (*irq_connect_cb)(void);
@ -69,6 +71,7 @@ struct i2c_esp32_config {
int index; int index;
irq_connect_cb connect_irq; irq_connect_cb connect_irq;
const char *clock_name;
const struct { const struct {
int sda_out; int sda_out;
@ -82,7 +85,7 @@ struct i2c_esp32_config {
int sda; int sda;
} pins; } pins;
const struct esp32_peripheral peripheral; const clock_control_subsys_t peripheral_id;
const struct { const struct {
bool tx_lsb_first; bool tx_lsb_first;
@ -126,7 +129,7 @@ static int i2c_esp32_configure_pins(int pin, int matrix_out, int matrix_in)
return 0; 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) uint32_t speed)
{ {
static const uint32_t speed_to_freq_tbl[] = { 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_HIGH] = 0,
[I2C_SPEED_ULTRA] = 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 freq_hz = speed_to_freq_tbl[speed];
uint32_t period; uint32_t period;
@ -143,8 +151,13 @@ static int i2c_esp32_configure_speed(const struct i2c_esp32_config *config,
return -ENOTSUP; 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 */ period /= 2U; /* Set hold and setup times to 1/2th of period */
esp32_set_mask32(period << I2C_SCL_LOW_PERIOD_S, 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; 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 */ /* MSB or LSB first is configurable for both TX and RX */
if (config->mode.tx_lsb_first) { 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; v |= I2C_CLK_EN;
sys_write32(v, I2C_CTR_REG(config->index)); 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) { if (ret < 0) {
goto out; goto out;
} }
@ -578,6 +591,8 @@ static void i2c_esp32_connect_irq_0(void)
static const struct i2c_esp32_config i2c_esp32_config_0 = { static const struct i2c_esp32_config i2c_esp32_config_0 = {
.index = 0, .index = 0,
.connect_irq = i2c_esp32_connect_irq_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 = { .sig = {
.sda_out = I2CEXT0_SDA_OUT_IDX, .sda_out = I2CEXT0_SDA_OUT_IDX,
.sda_in = I2CEXT0_SDA_IN_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), .scl = DT_INST_PROP(0, scl_pin),
.sda = DT_INST_PROP(0, sda_pin), .sda = DT_INST_PROP(0, sda_pin),
}, },
.peripheral = {
.clk = DPORT_I2C_EXT0_CLK_EN,
.rst = DPORT_I2C_EXT0_RST,
},
.mode = { .mode = {
.tx_lsb_first = .tx_lsb_first =
IS_ENABLED(CONFIG_I2C_ESP32_0_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 = { static const struct i2c_esp32_config i2c_esp32_config_1 = {
.index = 1, .index = 1,
.connect_irq = i2c_esp32_connect_irq_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 = { .sig = {
.sda_out = I2CEXT1_SDA_OUT_IDX, .sda_out = I2CEXT1_SDA_OUT_IDX,
.sda_in = I2CEXT1_SDA_IN_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), .scl = DT_INST_PROP(1, scl_pin),
.sda = DT_INST_PROP(1, sda_pin), .sda = DT_INST_PROP(1, sda_pin),
}, },
.peripheral = {
.clk = DPORT_I2C_EXT1_CLK_EN,
.rst = DPORT_I2C_EXT1_RST,
},
.mode = { .mode = {
.tx_lsb_first = .tx_lsb_first =
IS_ENABLED(CONFIG_I2C_ESP32_1_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; const struct i2c_esp32_config *config = dev->config_info;
struct i2c_esp32_data *data = dev->driver_data; struct i2c_esp32_data *data = dev->driver_data;
uint32_t bitrate_cfg = i2c_map_dt_bitrate(config->bitrate); 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(); unsigned int key = irq_lock();
k_sem_init(&data->fifo_sem, 1, 1); k_sem_init(&data->fifo_sem, 1, 1);

View file

@ -17,6 +17,7 @@
#include <device.h> #include <device.h>
#include <soc.h> #include <soc.h>
#include <drivers/uart.h> #include <drivers/uart.h>
#include <drivers/clock_control.h>
#include <errno.h> #include <errno.h>
#include <sys/util.h> #include <sys/util.h>
@ -62,6 +63,7 @@ struct uart_esp32_regs_t {
struct uart_esp32_config { struct uart_esp32_config {
struct uart_device_config dev_conf; struct uart_device_config dev_conf;
const char *clock_name;
const struct { const struct {
int tx_out; int tx_out;
@ -77,7 +79,7 @@ struct uart_esp32_config {
int cts; int cts;
} pins; } pins;
const struct esp32_peripheral peripheral; const clock_control_subsys_t peripheral_id;
const struct { const struct {
int source; int source;
@ -88,6 +90,7 @@ struct uart_esp32_config {
/* driver data */ /* driver data */
struct uart_esp32_data { struct uart_esp32_data {
struct uart_config uart_config; struct uart_config uart_config;
struct device *clock_dev;
#ifdef CONFIG_UART_INTERRUPT_DRIVEN #ifdef CONFIG_UART_INTERRUPT_DRIVEN
uart_irq_callback_user_data_t irq_cb; uart_irq_callback_user_data_t irq_cb;
void *irq_cb_data; 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) 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); uint32_t clk_div = (((sys_clk_freq) << 4) / baudrate);
while (UART_TXFIFO_COUNT(DEV_BASE(dev)->status)) { 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_TX_FIFO_THRESH << UART_TXFIFO_EMPTY_THRHD_S);
uart_esp32_configure_pins(dev); 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 * 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) 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); uart_esp32_configure(dev, &DEV_DATA(dev)->uart_config);
#ifdef CONFIG_UART_INTERRUPT_DRIVEN #ifdef CONFIG_UART_INTERRUPT_DRIVEN
@ -483,16 +499,11 @@ static const struct uart_esp32_config uart_esp32_cfg_port_##idx = { \
.dev_conf = { \ .dev_conf = { \
.base = \ .base = \
(uint8_t *)DT_INST_REG_ADDR(idx), \ (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) \ ESP32_UART_IRQ_HANDLER_FUNC(idx) \
}, \ }, \
\ \
.peripheral = { \ .clock_name = DT_INST_CLOCKS_LABEL(idx), \
.clk = DPORT_UART##idx##_CLK_EN, \ \
.rst = DPORT_UART##idx##_RST, \
}, \
\
.signals = { \ .signals = { \
.tx_out = U##idx##TXD_OUT_IDX, \ .tx_out = U##idx##TXD_OUT_IDX, \
.rx_in = U##idx##RXD_IN_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), \ .cts = DT_INST_PROP(idx, cts_pin), \
)) \ )) \
}, \ }, \
\ \
.peripheral_id = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(idx, offset), \
.irq = { \ .irq = { \
.source = ETS_UART##idx##_INTR_SOURCE, \ .source = ETS_UART##idx##_INTR_SOURCE, \
.line = INST_##idx##_ESPRESSIF_ESP32_UART_IRQ_0, \ .line = INST_##idx##_ESPRESSIF_ESP32_UART_IRQ_0, \

View file

@ -21,14 +21,14 @@
device_type = "cpu"; device_type = "cpu";
compatible = "cadence,tensilica-xtensa-lx6"; compatible = "cadence,tensilica-xtensa-lx6";
reg = <0>; reg = <0>;
clock-source = <ESP32_CLK_SRC_XTAL>; clock-source = <ESP32_CLK_SRC_PLL>;
}; };
cpu1: cpu@1 { cpu1: cpu@1 {
device_type = "cpu"; device_type = "cpu";
compatible = "cadence,tensilica-xtensa-lx6"; compatible = "cadence,tensilica-xtensa-lx6";
reg = <1>; reg = <1>;
clock-source = <ESP32_CLK_SRC_XTAL>; clock-source = <ESP32_CLK_SRC_PLL>;
}; };
}; };
@ -55,6 +55,7 @@
reg = <0x3ff40000 0x400>; reg = <0x3ff40000 0x400>;
/* interrupts = <12>; - FIXME: Enable interrupts when interrupt-controller got supported in device tree */ /* interrupts = <12>; - FIXME: Enable interrupts when interrupt-controller got supported in device tree */
label = "UART_0"; label = "UART_0";
clocks = <&rtc ESP32_UART0_MODULE>;
status = "disabled"; status = "disabled";
}; };
@ -63,6 +64,7 @@
reg = <0x3ff50000 0x400>; reg = <0x3ff50000 0x400>;
/* interrupts = <17>; - FIXME: Enable interrupts when interrupt-controller got supported in device tree */ /* interrupts = <17>; - FIXME: Enable interrupts when interrupt-controller got supported in device tree */
label = "UART_1"; label = "UART_1";
clocks = <&rtc ESP32_UART1_MODULE>;
status = "disabled"; status = "disabled";
}; };
@ -71,6 +73,7 @@
reg = <0x3ff6E000 0x400>; reg = <0x3ff6E000 0x400>;
/* interrupts = <18>; - FIXME: Enable interrupts when interrupt-controller got supported in device tree */ /* interrupts = <18>; - FIXME: Enable interrupts when interrupt-controller got supported in device tree */
label = "UART_2"; label = "UART_2";
clocks = <&rtc ESP32_UART2_MODULE>;
status = "disabled"; status = "disabled";
}; };
@ -104,6 +107,7 @@
reg = <0x3ff53000 0x1000>; reg = <0x3ff53000 0x1000>;
/* interrupts = <8>; - FIXME: Enable interrupts when interrupt-controller got supported in device tree */ /* interrupts = <8>; - FIXME: Enable interrupts when interrupt-controller got supported in device tree */
label = "I2C_0"; label = "I2C_0";
clocks = <&rtc ESP32_I2C_EXT0_MODULE>;
status = "disabled"; status = "disabled";
}; };
@ -114,6 +118,7 @@
reg = <0x3ff67000 0x1000>; reg = <0x3ff67000 0x1000>;
/* interrupts = <9>; - FIXME: Enable interrupts when interrupt-controller got supported in device tree */ /* interrupts = <9>; - FIXME: Enable interrupts when interrupt-controller got supported in device tree */
label = "I2C_1"; label = "I2C_1";
clocks = <&rtc ESP32_I2C_EXT1_MODULE>;
status = "disabled"; status = "disabled";
}; };

View file

@ -14,17 +14,6 @@
#include <stdbool.h> #include <stdbool.h>
#include <arch/xtensa/arch.h> #include <arch/xtensa/arch.h>
/**
* @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) static inline void esp32_set_mask32(uint32_t v, uint32_t mem_addr)
{ {
sys_write32(sys_read32(mem_addr) | v, 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); 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, extern int esp32_rom_intr_matrix_set(int cpu_no,
int interrupt_src, int interrupt_src,
int interrupt_line); int interrupt_line);