1 /*
2 * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT espressif_esp32_dac
8
9 #include <soc.h>
10 #include <zephyr/device.h>
11 #include <zephyr/drivers/dac.h>
12 #include <zephyr/drivers/clock_control.h>
13 #include <hal/rtc_io_types.h>
14 #include <hal/rtc_io_hal.h>
15 #include <hal/rtc_io_ll.h>
16 #include "driver/dac.h"
17
18 #include <zephyr/logging/log.h>
19 LOG_MODULE_REGISTER(esp32_dac, CONFIG_DAC_LOG_LEVEL);
20
21 struct dac_esp32_config {
22 int irq_source;
23 const struct device *clock_dev;
24 clock_control_subsys_t clock_subsys;
25 };
26
dac_esp32_write_value(const struct device * dev,uint8_t channel,uint32_t value)27 static int dac_esp32_write_value(const struct device *dev,
28 uint8_t channel, uint32_t value)
29 {
30 ARG_UNUSED(dev);
31
32 dac_output_voltage(channel, value);
33
34 return 0;
35 }
36
dac_esp32_channel_setup(const struct device * dev,const struct dac_channel_cfg * channel_cfg)37 static int dac_esp32_channel_setup(const struct device *dev,
38 const struct dac_channel_cfg *channel_cfg)
39 {
40 ARG_UNUSED(dev);
41
42 if (channel_cfg->channel_id > SOC_DAC_CHAN_NUM) {
43 LOG_ERR("Channel %d is not valid", channel_cfg->channel_id);
44 return -EINVAL;
45 }
46
47 if (channel_cfg->internal) {
48 LOG_ERR("Internal channels not supported");
49 return -ENOTSUP;
50 }
51
52 dac_output_enable(channel_cfg->channel_id);
53
54 return 0;
55 }
56
dac_esp32_init(const struct device * dev)57 static int dac_esp32_init(const struct device *dev)
58 {
59 const struct dac_esp32_config *cfg = dev->config;
60
61 if (!cfg->clock_dev) {
62 LOG_ERR("Clock device missing");
63 return -EINVAL;
64 }
65
66 if (!device_is_ready(cfg->clock_dev)) {
67 LOG_ERR("Clock device not ready");
68 return -ENODEV;
69 }
70
71 if (clock_control_on(cfg->clock_dev, (clock_control_subsys_t)cfg->clock_subsys) != 0) {
72 LOG_ERR("DAC clock setup failed (%d)", -EIO);
73 return -EIO;
74 }
75
76 return 0;
77 }
78
79 static DEVICE_API(dac, dac_esp32_driver_api) = {
80 .channel_setup = dac_esp32_channel_setup,
81 .write_value = dac_esp32_write_value
82 };
83
84 #define ESP32_DAC_INIT(id) \
85 \
86 static const struct dac_esp32_config dac_esp32_config_##id = { \
87 .irq_source = DT_INST_IRQN(id), \
88 .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(id)), \
89 .clock_subsys = (clock_control_subsys_t) DT_INST_CLOCKS_CELL(id, offset), \
90 }; \
91 \
92 DEVICE_DT_INST_DEFINE(id, \
93 &dac_esp32_init, \
94 NULL, \
95 NULL, \
96 &dac_esp32_config_##id, \
97 POST_KERNEL, \
98 CONFIG_DAC_INIT_PRIORITY, \
99 &dac_esp32_driver_api);
100
101 DT_INST_FOREACH_STATUS_OKAY(ESP32_DAC_INIT);
102