1 /*
2 * Copyright (c) 2020 Libre Solar Technologies GmbH
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT st_stm32_dac
8
9 #include <errno.h>
10
11 #include <zephyr/drivers/dac.h>
12 #include <zephyr/drivers/pinctrl.h>
13 #include <zephyr/device.h>
14 #include <zephyr/kernel.h>
15 #include <zephyr/init.h>
16 #include <soc.h>
17 #include <stm32_ll_dac.h>
18
19 #define LOG_LEVEL CONFIG_DAC_LOG_LEVEL
20 #include <zephyr/logging/log.h>
21 LOG_MODULE_REGISTER(dac_stm32);
22
23 #include <zephyr/drivers/clock_control/stm32_clock_control.h>
24
25 /* some low-end MCUs have DAC with only one channel */
26 #ifdef LL_DAC_CHANNEL_2
27 #define STM32_CHANNEL_COUNT 2
28 #else
29 #define STM32_CHANNEL_COUNT 1
30 #endif
31
32 /* first channel always named 1 */
33 #define STM32_FIRST_CHANNEL 1
34
35 #define CHAN(n) LL_DAC_CHANNEL_##n
36 static const uint32_t table_channels[] = {
37 CHAN(1),
38 #ifdef LL_DAC_CHANNEL_2
39 CHAN(2),
40 #endif
41 };
42
43 /* Read-only driver configuration */
44 struct dac_stm32_cfg {
45 /* DAC instance. */
46 DAC_TypeDef *base;
47 /* Clock configuration. */
48 struct stm32_pclken pclken;
49 /* pinctrl configurations. */
50 const struct pinctrl_dev_config *pcfg;
51 };
52
53 /* Runtime driver data */
54 struct dac_stm32_data {
55 uint8_t channel_count;
56 uint8_t resolution;
57 };
58
dac_stm32_write_value(const struct device * dev,uint8_t channel,uint32_t value)59 static int dac_stm32_write_value(const struct device *dev,
60 uint8_t channel, uint32_t value)
61 {
62 struct dac_stm32_data *data = dev->data;
63 const struct dac_stm32_cfg *cfg = dev->config;
64
65 if (channel - STM32_FIRST_CHANNEL >= data->channel_count ||
66 channel < STM32_FIRST_CHANNEL) {
67 LOG_ERR("Channel %d is not valid", channel);
68 return -EINVAL;
69 }
70
71 if (value >= BIT(data->resolution)) {
72 LOG_ERR("Value %d is out of range", value);
73 return -EINVAL;
74 }
75
76 if (data->resolution == 8) {
77 LL_DAC_ConvertData8RightAligned(cfg->base,
78 table_channels[channel - STM32_FIRST_CHANNEL], value);
79 } else if (data->resolution == 12) {
80 LL_DAC_ConvertData12RightAligned(cfg->base,
81 table_channels[channel - STM32_FIRST_CHANNEL], value);
82 }
83
84 return 0;
85 }
86
dac_stm32_channel_setup(const struct device * dev,const struct dac_channel_cfg * channel_cfg)87 static int dac_stm32_channel_setup(const struct device *dev,
88 const struct dac_channel_cfg *channel_cfg)
89 {
90 struct dac_stm32_data *data = dev->data;
91 const struct dac_stm32_cfg *cfg = dev->config;
92 uint32_t cfg_setting, channel;
93
94 if ((channel_cfg->channel_id - STM32_FIRST_CHANNEL >=
95 data->channel_count) ||
96 (channel_cfg->channel_id < STM32_FIRST_CHANNEL)) {
97 LOG_ERR("Channel %d is not valid", channel_cfg->channel_id);
98 return -EINVAL;
99 }
100
101 if ((channel_cfg->resolution == 8) ||
102 (channel_cfg->resolution == 12)) {
103 data->resolution = channel_cfg->resolution;
104 } else {
105 LOG_ERR("Resolution not supported");
106 return -ENOTSUP;
107 }
108
109 channel = table_channels[channel_cfg->channel_id - STM32_FIRST_CHANNEL];
110
111 if (channel_cfg->buffered) {
112 cfg_setting = LL_DAC_OUTPUT_BUFFER_ENABLE;
113 } else {
114 cfg_setting = LL_DAC_OUTPUT_BUFFER_DISABLE;
115 }
116
117 LL_DAC_SetOutputBuffer(cfg->base, channel, cfg_setting);
118
119 #if defined(LL_DAC_OUTPUT_CONNECT_INTERNAL)
120 /* If the DAC supports internal connections set it based on configuration */
121 if (channel_cfg->internal) {
122 cfg_setting = LL_DAC_OUTPUT_CONNECT_INTERNAL;
123 } else {
124 cfg_setting = LL_DAC_OUTPUT_CONNECT_GPIO;
125 }
126
127 LL_DAC_SetOutputConnection(cfg->base, channel, cfg_setting);
128 #else
129 if (channel_cfg->internal) {
130 LOG_ERR("Internal connections not supported");
131 return -ENOTSUP;
132 }
133 #endif /* LL_DAC_OUTPUT_CONNECT_INTERNAL */
134
135 LL_DAC_Enable(cfg->base, channel);
136
137 LOG_DBG("Channel setup succeeded!");
138
139 return 0;
140 }
141
dac_stm32_init(const struct device * dev)142 static int dac_stm32_init(const struct device *dev)
143 {
144 const struct dac_stm32_cfg *cfg = dev->config;
145 int err;
146
147 /* enable clock for subsystem */
148 const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
149
150 if (!device_is_ready(clk)) {
151 LOG_ERR("clock control device not ready");
152 return -ENODEV;
153 }
154
155 if (clock_control_on(clk,
156 (clock_control_subsys_t) &cfg->pclken) != 0) {
157 return -EIO;
158 }
159
160 /* Configure dt provided device signals when available */
161 err = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
162 if ((err < 0) && (err != -ENOENT)) {
163 LOG_ERR("DAC pinctrl setup failed (%d)", err);
164 return err;
165 }
166
167 return 0;
168 }
169
170 static DEVICE_API(dac, api_stm32_driver_api) = {
171 .channel_setup = dac_stm32_channel_setup,
172 .write_value = dac_stm32_write_value
173 };
174
175
176 #define STM32_DAC_INIT(index) \
177 \
178 PINCTRL_DT_INST_DEFINE(index); \
179 \
180 static const struct dac_stm32_cfg dac_stm32_cfg_##index = { \
181 .base = (DAC_TypeDef *)DT_INST_REG_ADDR(index), \
182 .pclken = { \
183 .enr = DT_INST_CLOCKS_CELL(index, bits), \
184 .bus = DT_INST_CLOCKS_CELL(index, bus), \
185 }, \
186 .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(index), \
187 }; \
188 \
189 static struct dac_stm32_data dac_stm32_data_##index = { \
190 .channel_count = STM32_CHANNEL_COUNT \
191 }; \
192 \
193 DEVICE_DT_INST_DEFINE(index, &dac_stm32_init, NULL, \
194 &dac_stm32_data_##index, \
195 &dac_stm32_cfg_##index, POST_KERNEL, \
196 CONFIG_DAC_INIT_PRIORITY, \
197 &api_stm32_driver_api);
198
199 DT_INST_FOREACH_STATUS_OKAY(STM32_DAC_INIT)
200