1 /*
2  * Copyright (C) 2021 Alibaba Group Holding Limited
3  */
4 
5 #include <stdint.h>
6 #include <errno.h>
7 #include <stdbool.h>
8 #include <aos/kernel.h>
9 #include <aos/list.h>
10 #include <aos/adc.h>
11 #include <aos/adc_core.h>
12 
13 #define AOS_ADC_CHECK_NULL(x) \
14     do { \
15         if ((x) == NULL) { \
16             return -EINVAL; \
17         } \
18     } while (0)
19 
aos_adc_get(aos_adc_ref_t * ref,uint32_t id)20 aos_status_t aos_adc_get(aos_adc_ref_t *ref, uint32_t id)
21 {
22     AOS_ADC_CHECK_NULL(ref);
23 
24     return aos_dev_get(ref, AOS_DEV_TYPE_ADC, id);
25 }
26 
aos_adc_put(aos_adc_ref_t * ref)27 void aos_adc_put(aos_adc_ref_t *ref)
28 {
29     if (ref == NULL)
30         return;
31 
32     aos_dev_put(ref);
33 }
34 
aos_adc_set_sample_time(aos_adc_ref_t * ref,int32_t channel,uint32_t time)35 aos_status_t aos_adc_set_sample_time(aos_adc_ref_t *ref, int32_t channel, uint32_t time)
36 {
37     aos_status_t ret;
38     aos_adc_t *adc;
39 
40     AOS_ADC_CHECK_NULL(ref);
41     adc = aos_container_of(ref->dev, aos_adc_t, dev);
42     if (adc->ops->set_sample_time == NULL)
43         return -ENOTSUP;
44 
45     aos_dev_lock(ref->dev);
46     /* Convert time(unit:us) into the number of adc clock cycle. */
47     ret = adc->ops->set_sample_time(adc, channel, (time * adc->freq) / 1000000U);
48     aos_dev_unlock(ref->dev);
49     return ret;
50 }
51 
aos_adc_set_mode(aos_adc_ref_t * ref,aos_adc_mode_t mode)52 aos_status_t aos_adc_set_mode(aos_adc_ref_t *ref, aos_adc_mode_t mode)
53 {
54     aos_status_t ret;
55     aos_adc_t *adc;
56 
57     AOS_ADC_CHECK_NULL(ref);
58     adc = aos_container_of(ref->dev, aos_adc_t, dev);
59     if (adc->ops->set_mode == NULL)
60         return -ENOTSUP;
61 
62     aos_dev_lock(ref->dev);
63     ret = adc->ops->set_mode(adc, mode);
64     aos_dev_unlock(ref->dev);
65     return ret;
66 }
67 
aos_adc_get_resolution(aos_adc_ref_t * ref,uint32_t * resolution)68 aos_status_t aos_adc_get_resolution(aos_adc_ref_t *ref, uint32_t *resolution)
69 {
70     aos_adc_t *adc;
71 
72     AOS_ADC_CHECK_NULL(ref);
73     AOS_ADC_CHECK_NULL(resolution);
74 
75     adc = aos_container_of(ref->dev, aos_adc_t, dev);
76     AOS_ADC_CHECK_NULL(adc);
77     *resolution = adc->resolution;
78 
79     return 0;
80 }
81 
aos_adc_get_range(aos_adc_ref_t * ref,int32_t channel,uint32_t * range)82 aos_status_t aos_adc_get_range(aos_adc_ref_t *ref, int32_t channel, uint32_t *range)
83 {
84     aos_status_t ret;
85     aos_adc_t *adc;
86 
87     AOS_ADC_CHECK_NULL(ref);
88     AOS_ADC_CHECK_NULL(range);
89 
90     adc = aos_container_of(ref->dev, aos_adc_t, dev);
91     AOS_ADC_CHECK_NULL(adc);
92     if (adc->ops->get_range == NULL)
93         return -ENOTSUP;
94 
95     aos_dev_lock(ref->dev);
96     ret = adc->ops->get_range(adc, channel, range);
97     aos_dev_unlock(ref->dev);
98     return ret;
99 }
100 
aos_adc_read(aos_adc_ref_t * ref,int32_t channel,int32_t * data)101 aos_status_t aos_adc_read(aos_adc_ref_t *ref, int32_t channel, int32_t *data)
102 {
103     aos_status_t ret;
104     aos_adc_t *adc;
105 
106     AOS_ADC_CHECK_NULL(ref);
107     AOS_ADC_CHECK_NULL(data);
108 
109     adc = aos_container_of(ref->dev, aos_adc_t, dev);
110     AOS_ADC_CHECK_NULL(adc);
111 
112     aos_dev_lock(ref->dev);
113     ret = adc->ops->read(adc, channel, data);
114     aos_dev_unlock(ref->dev);
115     return ret;
116 }
117 
aos_adc_read_voltage(aos_adc_ref_t * ref,int32_t channel,int32_t * data)118 aos_status_t aos_adc_read_voltage(aos_adc_ref_t *ref, int32_t channel, int32_t *data)
119 {
120     aos_status_t ret;
121     aos_adc_t *adc;
122 
123     AOS_ADC_CHECK_NULL(ref);
124     AOS_ADC_CHECK_NULL(data);
125 
126     adc = aos_container_of(ref->dev, aos_adc_t, dev);
127     AOS_ADC_CHECK_NULL(adc);
128 
129     aos_dev_lock(ref->dev);
130     ret = adc->ops->read_voltage(adc, channel, data);
131     aos_dev_unlock(ref->dev);
132     return ret;
133 }
134 
dev_adc_unregister(aos_dev_t * dev)135 static void dev_adc_unregister(aos_dev_t *dev)
136 {
137     aos_adc_t *adc = aos_container_of(dev, aos_adc_t, dev);
138 
139     if (adc->ops->unregister)
140         adc->ops->unregister(adc);
141 }
142 
dev_adc_get(aos_dev_ref_t * ref)143 static aos_status_t dev_adc_get(aos_dev_ref_t *ref)
144 {
145     aos_adc_t *adc = aos_container_of(ref->dev, aos_adc_t, dev);
146 
147     if (!aos_dev_ref_is_first(ref))
148         return 0;
149 
150     return adc->ops->startup(adc);
151 }
152 
dev_adc_put(aos_dev_ref_t * ref)153 static void dev_adc_put(aos_dev_ref_t *ref)
154 {
155     aos_adc_t *adc = aos_container_of(ref->dev, aos_adc_t, dev);
156 
157     if (!aos_dev_ref_is_last(ref))
158         return;
159 
160     adc->ops->shutdown(adc);
161 }
162 
163 static const aos_dev_ops_t dev_adc_ops = {
164     .unregister = dev_adc_unregister,
165     .get = dev_adc_get,
166     .put = dev_adc_put,
167 };
168 
aos_adc_register(aos_adc_t * adc)169 aos_status_t aos_adc_register(aos_adc_t *adc)
170 {
171     aos_status_t ret;
172 
173     AOS_ADC_CHECK_NULL(adc);
174 
175     /* startup/shutdown/read must be set. */
176     if ((adc->ops == NULL) || (adc->ops->startup == NULL) ||
177         (adc->ops->shutdown == NULL) || (adc->ops->read == NULL) ||
178         (adc->ops->read_voltage == NULL))
179         return -EINVAL;
180 
181     if ((adc->resolution == 0) || (adc->freq == 0))
182         return -EINVAL;
183 
184     adc->dev.type = AOS_DEV_TYPE_ADC;
185     adc->dev.ops = &dev_adc_ops;
186 #ifdef AOS_COMP_VFS
187     /* TODO: support vfs ops. */
188     adc->dev.vfs_helper.name[0] = '\0';
189     adc->dev.vfs_helper.ops = NULL;
190 #endif
191 
192     return aos_dev_register(&(adc->dev));
193 }
194 
aos_adc_unregister(uint32_t id)195 aos_status_t aos_adc_unregister(uint32_t id)
196 {
197     return aos_dev_unregister(AOS_DEV_TYPE_ADC, id);
198 }
199