1 /*
2 * Copyright 2023 NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT nxp_gau_dac
8
9 #include <zephyr/drivers/dac.h>
10
11 #include <fsl_dac.h>
12
13 #define LOG_LEVEL CONFIG_DAC_LOG_LEVEL
14 #include <zephyr/logging/log.h>
15 #include <zephyr/irq.h>
16 LOG_MODULE_REGISTER(nxp_gau_dac);
17
18 struct nxp_gau_dac_config {
19 DAC_Type *base;
20 dac_conversion_rate_t conversion_rate : 2;
21 dac_reference_voltage_source_t voltage_ref : 1;
22 dac_output_voltage_range_t output_range : 2;
23 };
24
convert_channel_id(uint8_t channel_id)25 static inline dac_channel_id_t convert_channel_id(uint8_t channel_id)
26 {
27 switch (channel_id) {
28 case 0: return kDAC_ChannelA;
29 case 1: return kDAC_ChannelB;
30 default:
31 LOG_ERR("Invalid DAC channel ID");
32 return -EINVAL;
33 };
34 }
35
nxp_gau_dac_channel_setup(const struct device * dev,const struct dac_channel_cfg * channel_cfg)36 static int nxp_gau_dac_channel_setup(const struct device *dev,
37 const struct dac_channel_cfg *channel_cfg)
38 {
39 const struct nxp_gau_dac_config *config = dev->config;
40 dac_channel_config_t dac_channel_config = {0};
41 bool use_internal = true;
42
43 if (channel_cfg->resolution != 10) {
44 LOG_ERR("DAC only support 10 bit resolution");
45 return -EINVAL;
46 }
47
48 if (channel_cfg->internal && channel_cfg->buffered) {
49 LOG_ERR("DAC output can not be buffered and internal");
50 return -EINVAL;
51 } else if (channel_cfg->buffered) {
52 /* External and internal output are mutually exclusive */
53 LOG_WRN("Note: buffering DAC output to pad disconnects internal output");
54 use_internal = false;
55 }
56
57 dac_channel_config.waveType = kDAC_WaveNormal;
58 dac_channel_config.outMode =
59 use_internal ? kDAC_ChannelOutputInternal : kDAC_ChannelOutputPAD;
60 dac_channel_config.timingMode = kDAC_NonTimingCorrelated;
61 dac_channel_config.enableTrigger = false;
62 dac_channel_config.enableDMA = false;
63 dac_channel_config.enableConversion = true;
64
65 DAC_SetChannelConfig(config->base,
66 (uint32_t)convert_channel_id(channel_cfg->channel_id),
67 &dac_channel_config);
68
69 return 0;
70 };
71
nxp_gau_dac_write_value(const struct device * dev,uint8_t channel,uint32_t value)72 static int nxp_gau_dac_write_value(const struct device *dev,
73 uint8_t channel, uint32_t value)
74 {
75 const struct nxp_gau_dac_config *config = dev->config;
76
77 DAC_SetChannelData(config->base,
78 (uint32_t)convert_channel_id(channel),
79 (uint16_t)value);
80 return 0;
81 };
82
83 static DEVICE_API(dac, nxp_gau_dac_driver_api) = {
84 .channel_setup = nxp_gau_dac_channel_setup,
85 .write_value = nxp_gau_dac_write_value,
86 };
87
nxp_gau_dac_init(const struct device * dev)88 static int nxp_gau_dac_init(const struct device *dev)
89 {
90 const struct nxp_gau_dac_config *config = dev->config;
91 dac_config_t dac_cfg;
92
93 DAC_GetDefaultConfig(&dac_cfg);
94
95 dac_cfg.conversionRate = config->conversion_rate;
96 dac_cfg.refSource = config->voltage_ref;
97 dac_cfg.rangeSelect = config->output_range;
98
99 DAC_Init(config->base, &dac_cfg);
100
101 return 0;
102 };
103
104 #define NXP_GAU_DAC_INIT(inst) \
105 \
106 const struct nxp_gau_dac_config nxp_gau_dac_##inst##_config = { \
107 .base = (DAC_Type *) DT_INST_REG_ADDR(inst), \
108 .voltage_ref = DT_INST_ENUM_IDX(inst, nxp_dac_reference), \
109 .conversion_rate = DT_INST_ENUM_IDX(inst, nxp_conversion_rate), \
110 .output_range = DT_INST_ENUM_IDX(inst, \
111 nxp_output_voltage_range), \
112 }; \
113 \
114 \
115 DEVICE_DT_INST_DEFINE(inst, &nxp_gau_dac_init, NULL, \
116 NULL, \
117 &nxp_gau_dac_##inst##_config, \
118 POST_KERNEL, CONFIG_DAC_INIT_PRIORITY, \
119 &nxp_gau_dac_driver_api);
120
121 DT_INST_FOREACH_STATUS_OKAY(NXP_GAU_DAC_INIT)
122