diff --git a/boards/xtensa/esp32/esp32.yaml b/boards/xtensa/esp32/esp32.yaml index 52bd422d89..b3fdcf7f22 100644 --- a/boards/xtensa/esp32/esp32.yaml +++ b/boards/xtensa/esp32/esp32.yaml @@ -11,6 +11,7 @@ supported: - uart - nvs - pwm + - dac testing: ignore_tags: - net diff --git a/drivers/dac/CMakeLists.txt b/drivers/dac/CMakeLists.txt index d22de0fe6c..b0e86e3bd4 100644 --- a/drivers/dac/CMakeLists.txt +++ b/drivers/dac/CMakeLists.txt @@ -13,4 +13,5 @@ zephyr_library_sources_ifdef(CONFIG_DAC_SHELL dac_shell.c) zephyr_library_sources_ifdef(CONFIG_DAC_MCP4725 dac_mcp4725.c) zephyr_library_sources_ifdef(CONFIG_DAC_MCP4728 dac_mcp4728.c) zephyr_library_sources_ifdef(CONFIG_DAC_GD32 dac_gd32.c) +zephyr_library_sources_ifdef(CONFIG_DAC_ESP32 dac_esp32.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE dac_handlers.c) diff --git a/drivers/dac/Kconfig b/drivers/dac/Kconfig index d48fde6d44..7902abeaac 100644 --- a/drivers/dac/Kconfig +++ b/drivers/dac/Kconfig @@ -48,4 +48,6 @@ source "drivers/dac/Kconfig.mcp4728" source "drivers/dac/Kconfig.gd32" +source "drivers/dac/Kconfig.esp32" + endif # DAC diff --git a/drivers/dac/Kconfig.esp32 b/drivers/dac/Kconfig.esp32 new file mode 100644 index 0000000000..4327a0d768 --- /dev/null +++ b/drivers/dac/Kconfig.esp32 @@ -0,0 +1,11 @@ +# ESP32 DAC configuration options + +# Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config DAC_ESP32 + bool "ESP32 DAC driver" + default y + depends on DT_HAS_ESPRESSIF_ESP32_DAC_ENABLED + help + Enable the ESP32 DAC driver diff --git a/drivers/dac/dac_esp32.c b/drivers/dac/dac_esp32.c new file mode 100644 index 0000000000..7b7573ce24 --- /dev/null +++ b/drivers/dac/dac_esp32.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT espressif_esp32_dac + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "driver/dac_common.h" + +#include +LOG_MODULE_REGISTER(esp32_dac, CONFIG_DAC_LOG_LEVEL); + +struct dac_esp32_config { + int irq_source; + const struct device *clock_dev; + clock_control_subsys_t clock_subsys; +}; + +static int dac_esp32_write_value(const struct device *dev, + uint8_t channel, uint32_t value) +{ + ARG_UNUSED(dev); + + dac_output_voltage(channel, value); + + return 0; +} + +static int dac_esp32_channel_setup(const struct device *dev, + const struct dac_channel_cfg *channel_cfg) +{ + ARG_UNUSED(dev); + + if (channel_cfg->channel_id > DAC_CHANNEL_MAX) { + LOG_ERR("Channel %d is not valid", channel_cfg->channel_id); + return -EINVAL; + } + + dac_output_enable(channel_cfg->channel_id); + + return 0; +} + +static int dac_esp32_init(const struct device *dev) +{ + const struct dac_esp32_config *cfg = dev->config; + + if (!cfg->clock_dev) { + LOG_ERR("Clock device missing"); + return -EINVAL; + } + + if (!device_is_ready(cfg->clock_dev)) { + LOG_ERR("Clock device not ready"); + return -ENODEV; + } + + if (clock_control_on(cfg->clock_dev, + (clock_control_subsys_t *) &cfg->clock_subsys) != 0) { + LOG_ERR("DAC clock setup failed (%d)", -EIO); + return -EIO; + } + + return 0; +} + +static const struct dac_driver_api dac_esp32_driver_api = { + .channel_setup = dac_esp32_channel_setup, + .write_value = dac_esp32_write_value +}; + +#define ESP32_DAC_INIT(id) \ + \ + static const struct dac_esp32_config dac_esp32_config_##id = { \ + .irq_source = DT_INST_IRQN(id), \ + .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(id)), \ + .clock_subsys = (clock_control_subsys_t) DT_INST_CLOCKS_CELL(id, offset), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(id, \ + &dac_esp32_init, \ + NULL, \ + NULL, \ + &dac_esp32_config_##id, \ + POST_KERNEL, \ + CONFIG_DAC_INIT_PRIORITY, \ + &dac_esp32_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(ESP32_DAC_INIT); diff --git a/dts/bindings/dac/espressif,esp32-dac.yaml b/dts/bindings/dac/espressif,esp32-dac.yaml new file mode 100644 index 0000000000..f86aecc156 --- /dev/null +++ b/dts/bindings/dac/espressif,esp32-dac.yaml @@ -0,0 +1,53 @@ +# Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +description: | + Espressif Digital to Analog converter (DAC) control node + is part of the RTC low-power domain and belongs to the SENSE + peripherals set. RTC peripherals has GPIOs controlled by the + RTCIO mux, which is separated from the main IO mux. + + Two GPIO pads can only be connected to the DAC peripheral. + + ESP32 pads + - GPIO25 as DAC channel 1 + - GPIO26 as DAC channel 2 + + ESP32-S2 pads + - GPIO17 as DAC channel 1 + - GPIO18 as DAC channel 2 + + To enable the DAC peripheral it must be enabled in the board + dts, or in subsequent overlay file. + + &dac { + status = "okay"; + }; + + To specify the DAC channel to use, dts overlay must include + properties 'dac-channel-id', which uses zero based channel index. + Variable 'dac-resolution' must be also specified, although ESP32 + only supported resolution is 8bits. + + / { + zephyr,user { + dac = <&dac>; + dac-channel-id = <0>; + dac-resolution = <8>; + }; + }; + + NOTE: The DAC peripheral outputs are fixed to gpio pads, therefore + it does not need to be controlled by the pinctrl node. + +compatible: "espressif,esp32-dac" + +include: [dac-controller.yaml] + +properties: + + "#io-channel-cells": + const: 1 + +io-channel-cells: + - output diff --git a/dts/xtensa/espressif/esp32.dtsi b/dts/xtensa/espressif/esp32.dtsi index 9c8e908250..bf00f02ae3 100644 --- a/dts/xtensa/espressif/esp32.dtsi +++ b/dts/xtensa/espressif/esp32.dtsi @@ -354,6 +354,16 @@ interrupt-parent = <&intc>; status = "disabled"; }; + + dac: dac@3ff48800 { + compatible = "espressif,esp32-dac"; + reg = <0x3ff48800 0x100>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_SARADC_MODULE>; + #io-channel-cells = <1>; + status = "disabled"; + }; }; }; diff --git a/dts/xtensa/espressif/esp32s2.dtsi b/dts/xtensa/espressif/esp32s2.dtsi index 2247942fbc..cbfc1bae30 100644 --- a/dts/xtensa/espressif/esp32s2.dtsi +++ b/dts/xtensa/espressif/esp32s2.dtsi @@ -254,6 +254,16 @@ clocks = <&rtc ESP32_TIMG1_MODULE>; status = "disabled"; }; + + dac: dac@3f408800 { + compatible = "espressif,esp32-dac"; + reg = <0x3f408800 0x100>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_PERIPH_SARADC_MODULE>; + #io-channel-cells = <1>; + status = "disabled"; + }; }; }; diff --git a/include/zephyr/dt-bindings/pinctrl/esp32-gpio-sigmap.h b/include/zephyr/dt-bindings/pinctrl/esp32-gpio-sigmap.h index 41c2a513ab..b479715f75 100644 --- a/include/zephyr/dt-bindings/pinctrl/esp32-gpio-sigmap.h +++ b/include/zephyr/dt-bindings/pinctrl/esp32-gpio-sigmap.h @@ -419,4 +419,26 @@ #define ESP_SIG_IN_FUNC228 228 #define ESP_SIG_GPIO_OUT 256 +/* RTC-IO MUX */ +#define ESP_ADC1_CH0 0 +#define ESP_ADC1_CH1 1 +#define ESP_ADC1_CH2 2 +#define ESP_ADC1_CH3 3 +#define ESP_ADC1_CH6 4 +#define ESP_ADC1_CH7 5 +#define ESP_ADC2_CH8 6 +#define ESP_ADC2_CH9 7 +#define ESP_DAC1_OUT 6 +#define ESP_DAC2_OUT 7 +#define ESP_ADC1_CH5 8 +#define ESP_ADC1_CH4 9 +#define ESP_ADC2_CH0 10 +#define ESP_ADC2_CH1 11 +#define ESP_ADC2_CH2 12 +#define ESP_ADC2_CH3 13 +#define ESP_ADC2_CH4 14 +#define ESP_ADC2_CH5 15 +#define ESP_ADC2_CH6 16 +#define ESP_ADC2_CH7 17 + #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_ESP32_GPIO_SIGMAP_H_ */