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