1 /*
2 * Copyright (c) 2020 Henrik Brix Andersen <henrik@brixandersen.dk>
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT nxp_kinetis_dac
8
9 #include <zephyr/kernel.h>
10 #include <zephyr/drivers/dac.h>
11 #include <zephyr/logging/log.h>
12
13 #include <fsl_dac.h>
14
15 LOG_MODULE_REGISTER(dac_mcux_dac, CONFIG_DAC_LOG_LEVEL);
16
17 struct mcux_dac_config {
18 DAC_Type *base;
19 dac_reference_voltage_source_t reference;
20 bool low_power;
21 };
22
23 struct mcux_dac_data {
24 bool configured;
25 };
26
mcux_dac_channel_setup(const struct device * dev,const struct dac_channel_cfg * channel_cfg)27 static int mcux_dac_channel_setup(const struct device *dev,
28 const struct dac_channel_cfg *channel_cfg)
29 {
30 const struct mcux_dac_config *config = dev->config;
31 struct mcux_dac_data *data = dev->data;
32 dac_config_t dac_config;
33
34 if (channel_cfg->channel_id != 0) {
35 LOG_ERR("unsupported channel %d", channel_cfg->channel_id);
36 return -ENOTSUP;
37 }
38
39 if (channel_cfg->resolution != 12) {
40 LOG_ERR("unsupported resolution %d", channel_cfg->resolution);
41 return -ENOTSUP;
42 }
43
44 DAC_GetDefaultConfig(&dac_config);
45 dac_config.enableLowPowerMode = config->low_power;
46 dac_config.referenceVoltageSource = config->reference;
47
48 DAC_Init(config->base, &dac_config);
49
50 data->configured = true;
51
52 return 0;
53 }
54
mcux_dac_write_value(const struct device * dev,uint8_t channel,uint32_t value)55 static int mcux_dac_write_value(const struct device *dev, uint8_t channel,
56 uint32_t value)
57 {
58 const struct mcux_dac_config *config = dev->config;
59 struct mcux_dac_data *data = dev->data;
60
61 if (!data->configured) {
62 LOG_ERR("channel not initialized");
63 return -EINVAL;
64 }
65
66 if (channel != 0) {
67 LOG_ERR("unsupported channel %d", channel);
68 return -ENOTSUP;
69 }
70
71 if (value >= 4096) {
72 LOG_ERR("value %d out of range", value);
73 return -EINVAL;
74 }
75
76 /* Static operation */
77 DAC_EnableBuffer(config->base, false);
78
79 DAC_SetBufferValue(config->base, 0, value);
80 DAC_Enable(config->base, true);
81
82 return 0;
83 }
84
85 static const struct dac_driver_api mcux_dac_driver_api = {
86 .channel_setup = mcux_dac_channel_setup,
87 .write_value = mcux_dac_write_value,
88 };
89
90 #define TO_DAC_VREF_SRC(val) \
91 _DO_CONCAT(kDAC_ReferenceVoltageSourceVref, val)
92
93 #define MCUX_DAC_INIT(n) \
94 static struct mcux_dac_data mcux_dac_data_##n; \
95 \
96 static const struct mcux_dac_config mcux_dac_config_##n = { \
97 .base = (DAC_Type *)DT_INST_REG_ADDR(n), \
98 .reference = \
99 TO_DAC_VREF_SRC(DT_INST_PROP(n, voltage_reference)), \
100 .low_power = DT_INST_PROP(n, low_power_mode), \
101 }; \
102 \
103 DEVICE_DT_INST_DEFINE(n, NULL, NULL, \
104 &mcux_dac_data_##n, \
105 &mcux_dac_config_##n, \
106 POST_KERNEL, CONFIG_DAC_INIT_PRIORITY, \
107 &mcux_dac_driver_api);
108
109 DT_INST_FOREACH_STATUS_OKAY(MCUX_DAC_INIT)
110