1 /*
2  * Copyright (c) 2021 BrainCo Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT gd_gd32_dac
8 
9 #include <errno.h>
10 
11 #include <zephyr/drivers/clock_control.h>
12 #include <zephyr/drivers/clock_control/gd32.h>
13 #include <zephyr/drivers/pinctrl.h>
14 #include <zephyr/drivers/reset.h>
15 #include <zephyr/drivers/dac.h>
16 
17 #include <gd32_dac.h>
18 
19 #include <zephyr/logging/log.h>
20 LOG_MODULE_REGISTER(dac_gd32, CONFIG_DAC_LOG_LEVEL);
21 
22 /**
23  * For some gd32 series which only have 1 DAC, their HAL name may not same as others.
24  * Below definitions help to unify the HAL name.
25  */
26 #if defined(CONFIG_SOC_SERIES_GD32A50X)
27 #define DAC_CTL_DEN0 DAC_CTL_DEN
28 #define DAC0_R8DH    OUT_R8DH
29 #define DAC0_R12DH   OUT_R12DH
30 #elif defined(CONFIG_SOC_SERIES_GD32F3X0)
31 #define DAC_CTL_DEN0 DAC_CTL_DEN
32 #define DAC0_R8DH    DAC_R8DH
33 #define DAC0_R12DH   DAC_R12DH
34 #endif
35 
36 struct dac_gd32_config {
37 	uint32_t reg;
38 	uint16_t clkid;
39 	struct reset_dt_spec reset;
40 	const struct pinctrl_dev_config *pcfg;
41 	uint32_t num_channels;
42 	uint32_t reset_val;
43 };
44 
45 struct dac_gd32_data {
46 	uint8_t resolutions[2];
47 };
48 
dac_gd32_enable(uint8_t dacx)49 static void dac_gd32_enable(uint8_t dacx)
50 {
51 	switch (dacx) {
52 	case 0U:
53 		DAC_CTL |= DAC_CTL_DEN0;
54 		break;
55 #if DT_INST_PROP(0, num_channels) == 2
56 	case 1U:
57 		DAC_CTL |= DAC_CTL_DEN1;
58 		break;
59 #endif
60 	}
61 }
62 
dac_gd32_disable(uint8_t dacx)63 static void dac_gd32_disable(uint8_t dacx)
64 {
65 	switch (dacx) {
66 	case 0U:
67 		DAC_CTL &= ~DAC_CTL_DEN0;
68 		break;
69 #if DT_INST_PROP(0, num_channels) == 2
70 	case 1U:
71 		DAC_CTL &= ~DAC_CTL_DEN1;
72 		break;
73 #endif
74 	}
75 }
76 
dac_gd32_write(struct dac_gd32_data * data,uint8_t dacx,uint32_t value)77 static void dac_gd32_write(struct dac_gd32_data *data,
78 			   uint8_t dacx, uint32_t value)
79 {
80 	switch (dacx) {
81 	case 0U:
82 		if (data->resolutions[dacx] == 8U) {
83 			DAC0_R8DH = value;
84 		} else {
85 			DAC0_R12DH = value;
86 		}
87 		break;
88 #if DT_INST_PROP(0, num_channels) == 2
89 	case 1U:
90 		if (data->resolutions[dacx] == 8U) {
91 			DAC1_R8DH = value;
92 		} else {
93 			DAC1_R12DH = value;
94 		}
95 		break;
96 #endif
97 	}
98 }
99 
dac_gd32_channel_setup(const struct device * dev,const struct dac_channel_cfg * channel_cfg)100 static int dac_gd32_channel_setup(const struct device *dev,
101 				  const struct dac_channel_cfg *channel_cfg)
102 {
103 	struct dac_gd32_data *data = dev->data;
104 	const struct dac_gd32_config *config = dev->config;
105 	uint8_t dacx = channel_cfg->channel_id;
106 
107 	if (dacx >= config->num_channels) {
108 		return -ENOTSUP;
109 	}
110 
111 	/* GD32 DAC only support 8 or 12 bits resolution */
112 	if ((channel_cfg->resolution != 8U) &&
113 	    (channel_cfg->resolution != 12U)) {
114 		LOG_ERR("Only 8 and 12 bits resolutions are supported!");
115 		return -ENOTSUP;
116 	}
117 
118 	data->resolutions[dacx] = channel_cfg->resolution;
119 
120 	dac_gd32_disable(dacx);
121 	dac_gd32_write(data, dacx, config->reset_val);
122 	dac_gd32_enable(dacx);
123 
124 	return 0;
125 }
126 
dac_gd32_write_value(const struct device * dev,uint8_t dacx,uint32_t value)127 static int dac_gd32_write_value(const struct device *dev,
128 				uint8_t dacx, uint32_t value)
129 {
130 	struct dac_gd32_data *data = dev->data;
131 	const struct dac_gd32_config *config = dev->config;
132 
133 	if (dacx >= config->num_channels) {
134 		return -ENOTSUP;
135 	}
136 
137 	dac_gd32_write(data, dacx, value);
138 
139 	return 0;
140 }
141 
142 struct dac_driver_api dac_gd32_driver_api = {
143 	.channel_setup = dac_gd32_channel_setup,
144 	.write_value = dac_gd32_write_value
145 };
146 
dac_gd32_init(const struct device * dev)147 static int dac_gd32_init(const struct device *dev)
148 {
149 	const struct dac_gd32_config *cfg = dev->config;
150 	int ret;
151 
152 	ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
153 	if (ret < 0) {
154 		LOG_ERR("Failed to apply pinctrl state");
155 		return ret;
156 	}
157 
158 	(void)clock_control_on(GD32_CLOCK_CONTROLLER,
159 			       (clock_control_subsys_t)&cfg->clkid);
160 
161 	(void)reset_line_toggle_dt(&cfg->reset);
162 
163 	return 0;
164 }
165 
166 PINCTRL_DT_INST_DEFINE(0);
167 
168 static struct dac_gd32_data dac_gd32_data_0;
169 
170 static const struct dac_gd32_config dac_gd32_cfg_0 = {
171 	.reg = DT_INST_REG_ADDR(0),
172 	.clkid = DT_INST_CLOCKS_CELL(0, id),
173 	.reset = RESET_DT_SPEC_INST_GET(0),
174 	.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0),
175 	.num_channels = DT_INST_PROP(0, num_channels),
176 	.reset_val = DT_INST_PROP(0, reset_val),
177 };
178 
179 DEVICE_DT_INST_DEFINE(0, &dac_gd32_init, NULL, &dac_gd32_data_0,
180 		      &dac_gd32_cfg_0, POST_KERNEL, CONFIG_DAC_INIT_PRIORITY,
181 		      &dac_gd32_driver_api);
182