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