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 (data->resolution == 8) {
72 LL_DAC_ConvertData8RightAligned(cfg->base,
73 table_channels[channel - STM32_FIRST_CHANNEL], value);
74 } else if (data->resolution == 12) {
75 LL_DAC_ConvertData12RightAligned(cfg->base,
76 table_channels[channel - STM32_FIRST_CHANNEL], value);
77 }
78
79 return 0;
80 }
81
dac_stm32_channel_setup(const struct device * dev,const struct dac_channel_cfg * channel_cfg)82 static int dac_stm32_channel_setup(const struct device *dev,
83 const struct dac_channel_cfg *channel_cfg)
84 {
85 struct dac_stm32_data *data = dev->data;
86 const struct dac_stm32_cfg *cfg = dev->config;
87 uint32_t output_buffer;
88
89 if ((channel_cfg->channel_id - STM32_FIRST_CHANNEL >=
90 data->channel_count) ||
91 (channel_cfg->channel_id < STM32_FIRST_CHANNEL)) {
92 LOG_ERR("Channel %d is not valid", channel_cfg->channel_id);
93 return -EINVAL;
94 }
95
96 if ((channel_cfg->resolution == 8) ||
97 (channel_cfg->resolution == 12)) {
98 data->resolution = channel_cfg->resolution;
99 } else {
100 LOG_ERR("Resolution not supported");
101 return -ENOTSUP;
102 }
103
104 if (channel_cfg->buffered) {
105 output_buffer = LL_DAC_OUTPUT_BUFFER_ENABLE;
106 } else {
107 output_buffer = LL_DAC_OUTPUT_BUFFER_DISABLE;
108 }
109
110 LL_DAC_SetOutputBuffer(cfg->base,
111 table_channels[channel_cfg->channel_id - STM32_FIRST_CHANNEL],
112 output_buffer);
113
114 LL_DAC_Enable(cfg->base,
115 table_channels[channel_cfg->channel_id - STM32_FIRST_CHANNEL]);
116
117 LOG_DBG("Channel setup succeeded!");
118
119 return 0;
120 }
121
dac_stm32_init(const struct device * dev)122 static int dac_stm32_init(const struct device *dev)
123 {
124 const struct dac_stm32_cfg *cfg = dev->config;
125 int err;
126
127 /* enable clock for subsystem */
128 const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
129
130 if (!device_is_ready(clk)) {
131 LOG_ERR("clock control device not ready");
132 return -ENODEV;
133 }
134
135 if (clock_control_on(clk,
136 (clock_control_subsys_t) &cfg->pclken) != 0) {
137 return -EIO;
138 }
139
140 /* Configure dt provided device signals when available */
141 err = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
142 if (err < 0) {
143 LOG_ERR("DAC pinctrl setup failed (%d)", err);
144 return err;
145 }
146
147 return 0;
148 }
149
150 static const struct dac_driver_api api_stm32_driver_api = {
151 .channel_setup = dac_stm32_channel_setup,
152 .write_value = dac_stm32_write_value
153 };
154
155
156 #define STM32_DAC_INIT(index) \
157 \
158 PINCTRL_DT_INST_DEFINE(index); \
159 \
160 static const struct dac_stm32_cfg dac_stm32_cfg_##index = { \
161 .base = (DAC_TypeDef *)DT_INST_REG_ADDR(index), \
162 .pclken = { \
163 .enr = DT_INST_CLOCKS_CELL(index, bits), \
164 .bus = DT_INST_CLOCKS_CELL(index, bus), \
165 }, \
166 .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(index), \
167 }; \
168 \
169 static struct dac_stm32_data dac_stm32_data_##index = { \
170 .channel_count = STM32_CHANNEL_COUNT \
171 }; \
172 \
173 DEVICE_DT_INST_DEFINE(index, &dac_stm32_init, NULL, \
174 &dac_stm32_data_##index, \
175 &dac_stm32_cfg_##index, POST_KERNEL, \
176 CONFIG_DAC_INIT_PRIORITY, \
177 &api_stm32_driver_api);
178
179 DT_INST_FOREACH_STATUS_OKAY(STM32_DAC_INIT)
180