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