1 /*
2 * Copyright (c) 2020 Matija Tudan
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/drivers/i2c.h>
9 #include <zephyr/drivers/dac.h>
10 #include <zephyr/sys/util.h>
11 #include <zephyr/sys/byteorder.h>
12 #include <zephyr/sys/__assert.h>
13 #include <zephyr/logging/log.h>
14
15 LOG_MODULE_REGISTER(dac_dacx3608, CONFIG_DAC_LOG_LEVEL);
16
17 /* Register addresses */
18 #define DACX3608_REG_DEVICE_CONFIG 0x01U
19 #define DACX3608_REG_STATUS_TRIGGER 0x02U
20 #define DACX3608_REG_BRDCAST 0x03U
21 #define DACX3608_REG_DACA_DATA 0x08U
22
23 #define DAC43608_DEVICE_ID 0x500 /* STATUS_TRIGGER[DEVICE_ID] */
24 #define DAC53608_DEVICE_ID 0x300 /* STATUS_TRIGGER[DEVICE_ID] */
25 #define DACX3608_SW_RST 0x0A /* STATUS_TRIGGER[SW_RST] */
26 #define DACX3608_POR_DELAY 5
27 #define DACX3608_MAX_CHANNEL 8
28
29 struct dacx3608_config {
30 struct i2c_dt_spec bus;
31 uint8_t resolution;
32 };
33
34 struct dacx3608_data {
35 uint8_t configured;
36 };
37
dacx3608_reg_read(const struct device * dev,uint8_t reg,uint16_t * val)38 static int dacx3608_reg_read(const struct device *dev, uint8_t reg,
39 uint16_t *val)
40 {
41 const struct dacx3608_config *cfg = dev->config;
42
43 if (i2c_burst_read_dt(&cfg->bus, reg, (uint8_t *) val, 2) < 0) {
44 LOG_ERR("I2C read failed");
45 return -EIO;
46 }
47
48 *val = sys_be16_to_cpu(*val);
49
50 return 0;
51 }
52
dacx3608_reg_write(const struct device * dev,uint8_t reg,uint16_t val)53 static int dacx3608_reg_write(const struct device *dev, uint8_t reg,
54 uint16_t val)
55 {
56 const struct dacx3608_config *cfg = dev->config;
57 uint8_t buf[3] = {reg, val >> 8, val & 0xFF};
58
59 return i2c_write_dt(&cfg->bus, buf, sizeof(buf));
60 }
61
dacx3608_reg_update(const struct device * dev,uint8_t reg,uint16_t mask,bool setting)62 int dacx3608_reg_update(const struct device *dev, uint8_t reg,
63 uint16_t mask, bool setting)
64 {
65 uint16_t regval;
66 int ret;
67
68 ret = dacx3608_reg_read(dev, reg, ®val);
69 if (ret) {
70 return -EIO;
71 }
72
73 if (setting) {
74 regval |= mask;
75 } else {
76 regval &= ~mask;
77 }
78
79 ret = dacx3608_reg_write(dev, reg, regval);
80 if (ret) {
81 return ret;
82 }
83
84 return 0;
85 }
86
dacx3608_channel_setup(const struct device * dev,const struct dac_channel_cfg * channel_cfg)87 static int dacx3608_channel_setup(const struct device *dev,
88 const struct dac_channel_cfg *channel_cfg)
89 {
90 const struct dacx3608_config *config = dev->config;
91 struct dacx3608_data *data = dev->data;
92 bool setting = false;
93 int ret;
94
95 if (channel_cfg->channel_id > DACX3608_MAX_CHANNEL - 1) {
96 LOG_ERR("Unsupported channel %d", channel_cfg->channel_id);
97 return -ENOTSUP;
98 }
99
100 if (channel_cfg->resolution != config->resolution) {
101 LOG_ERR("Unsupported resolution %d", channel_cfg->resolution);
102 return -ENOTSUP;
103 }
104
105 if (channel_cfg->internal) {
106 LOG_ERR("Internal channels not supported");
107 return -ENOTSUP;
108 }
109
110 if (data->configured & BIT(channel_cfg->channel_id)) {
111 LOG_DBG("Channel %d already configured", channel_cfg->channel_id);
112 return 0;
113 }
114
115 /* Clear PDNn bit */
116 ret = dacx3608_reg_update(dev, DACX3608_REG_DEVICE_CONFIG,
117 BIT(channel_cfg->channel_id), setting);
118 if (ret) {
119 LOG_ERR("Unable to update DEVICE_CONFIG register");
120 return -EIO;
121 }
122
123 data->configured |= BIT(channel_cfg->channel_id);
124
125 LOG_DBG("Channel %d initialized", channel_cfg->channel_id);
126
127 return 0;
128 }
129
dacx3608_write_value(const struct device * dev,uint8_t channel,uint32_t value)130 static int dacx3608_write_value(const struct device *dev, uint8_t channel,
131 uint32_t value)
132 {
133 const struct dacx3608_config *config = dev->config;
134 struct dacx3608_data *data = dev->data;
135 uint16_t regval;
136 int ret;
137
138 const bool brdcast = (channel == DAC_CHANNEL_BROADCAST) ? 1 : 0;
139
140 if (!brdcast && (channel > DACX3608_MAX_CHANNEL - 1)) {
141 LOG_ERR("Unsupported channel %d", channel);
142 return -ENOTSUP;
143 }
144
145 /*
146 * Check if channel is initialized
147 * If broadcast channel is used, check if any channel is initialized
148 */
149 if ((brdcast && !data->configured) || (!(data->configured & BIT(channel)))) {
150 LOG_ERR("Channel %d not initialized", channel);
151 return -EINVAL;
152 }
153
154 if (value >= (1 << (config->resolution))) {
155 LOG_ERR("Value %d out of range", value);
156 return -EINVAL;
157 }
158
159 /*
160 * Shift passed value two times left because first two bits are Don't Care
161 *
162 * DACn_DATA register format:
163 *
164 * | 15 14 13 12 | 11 10 9 8 7 6 5 4 3 2 | 1 0 |
165 * |-------------|---------------------------------|------------|
166 * | Don't Care | DAC53608[9:0] / DAC43608[7:0] | Don't Care |
167 */
168 regval = value << 2;
169 regval &= 0xFFFF;
170
171 const uint8_t reg = brdcast ? DACX3608_REG_BRDCAST : DACX3608_REG_DACA_DATA + channel;
172
173 ret = dacx3608_reg_write(dev, reg, regval);
174 if (ret) {
175 LOG_ERR("Unable to set value %d on channel %d", value, channel);
176 return -EIO;
177 }
178
179 return 0;
180 }
181
dacx3608_soft_reset(const struct device * dev)182 static int dacx3608_soft_reset(const struct device *dev)
183 {
184 uint16_t regval = DACX3608_SW_RST;
185 int ret;
186
187 ret = dacx3608_reg_write(dev, DACX3608_REG_STATUS_TRIGGER, regval);
188 if (ret) {
189 return -EIO;
190 }
191 k_msleep(DACX3608_POR_DELAY);
192
193 return 0;
194 }
195
dacx3608_device_id_check(const struct device * dev)196 static int dacx3608_device_id_check(const struct device *dev)
197 {
198 uint16_t dev_id;
199 int ret;
200
201 ret = dacx3608_reg_read(dev, DACX3608_REG_STATUS_TRIGGER, &dev_id);
202 if (ret) {
203 LOG_ERR("Unable to read device ID");
204 return -EIO;
205 }
206
207 switch (dev_id) {
208 case DAC43608_DEVICE_ID:
209 case DAC53608_DEVICE_ID:
210 LOG_DBG("Device ID %#4x", dev_id);
211 break;
212 default:
213 LOG_ERR("Unknown Device ID %#4x", dev_id);
214 return -EIO;
215 }
216
217 return 0;
218 }
219
dacx3608_init(const struct device * dev)220 static int dacx3608_init(const struct device *dev)
221 {
222 const struct dacx3608_config *config = dev->config;
223 struct dacx3608_data *data = dev->data;
224 int ret;
225
226 if (!device_is_ready(config->bus.bus)) {
227 LOG_ERR("I2C device not ready");
228 return -ENODEV;
229 }
230
231 ret = dacx3608_soft_reset(dev);
232 if (ret) {
233 LOG_ERR("Soft-reset failed");
234 return ret;
235 }
236
237 ret = dacx3608_device_id_check(dev);
238 if (ret) {
239 return ret;
240 }
241
242 data->configured = 0;
243
244 LOG_DBG("Init complete");
245
246 return 0;
247 }
248
249 static DEVICE_API(dac, dacx3608_driver_api) = {
250 .channel_setup = dacx3608_channel_setup,
251 .write_value = dacx3608_write_value,
252 };
253
254 #define INST_DT_DACX3608(inst, t) DT_INST(inst, ti_dac##t)
255
256 #define DACX3608_DEVICE(t, n, res) \
257 static struct dacx3608_data dac##t##_data_##n; \
258 static const struct dacx3608_config dac##t##_config_##n = { \
259 .bus = I2C_DT_SPEC_GET(INST_DT_DACX3608(n, t)), \
260 .resolution = res, \
261 }; \
262 DEVICE_DT_DEFINE(INST_DT_DACX3608(n, t), \
263 &dacx3608_init, NULL, \
264 &dac##t##_data_##n, \
265 &dac##t##_config_##n, POST_KERNEL, \
266 CONFIG_DAC_DACX3608_INIT_PRIORITY, \
267 &dacx3608_driver_api)
268
269 /*
270 * DAC43608: 8-bit
271 */
272 #define DAC43608_DEVICE(n) DACX3608_DEVICE(43608, n, 8)
273
274 /*
275 * DAC53608: 10-bit
276 */
277 #define DAC53608_DEVICE(n) DACX3608_DEVICE(53608, n, 10)
278
279 #define CALL_WITH_ARG(arg, expr) expr(arg)
280
281 #define INST_DT_DACX3608_FOREACH(t, inst_expr) \
282 LISTIFY(DT_NUM_INST_STATUS_OKAY(ti_dac##t), \
283 CALL_WITH_ARG, (), inst_expr)
284
285 INST_DT_DACX3608_FOREACH(43608, DAC43608_DEVICE);
286 INST_DT_DACX3608_FOREACH(53608, DAC53608_DEVICE);
287