• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
17 #include "hcs_macro.h"
18 #include "hdf_config_macro.h"
19 #else
20 #include "device_resource_if.h"
21 #endif
22 
23 #include "hdf_device_desc.h"
24 #include "hdf_log.h"
25 #include "adc_core.h"
26 #include "osal_mem.h"
27 #include "osal_time.h"
28 #include "gd32f4xx_adc.h"
29 
30 #define HDF_LOG_TAG GD_ADC_MODULE_HDF
31 
32 #define CHANNEL_GROUP 0U
33 #define CHANNEL_LENGTH 1U
34 #define TIME_OUT 5000
35 #define BEGIN_TIMES 0
36 #define GPIO_REG_BASE 0x40020000
37 #define GPIO_BIT_PER_GROUP 16
38 #define GPIO_REG_STEP 0x400
39 #define DELAY_TIME_MS 1
40 #define ADC_REG_STEP 0x100
41 
42 struct AdcDeviceCntlr {
43     struct AdcDevice device;
44     uint32_t regBasePhy;
45     uint32_t deviceNum;
46     uint8_t channelNums;
47     uint8_t validChannels[16];
48     uint32_t outputPinNums[16];
49     uint8_t currentChannel;
50     uint32_t currentPinNum;
51 };
52 #define US_TO_MS_CONV (1000)
53 
AdcMDelay(uint32_t timeOut)54 static void AdcMDelay(uint32_t timeOut)
55 {
56     OsalTimespec startTick = {0, 0};
57     OsalTimespec endTick = {0, 0};
58     OsalTimespec diffTick = {0, 0};
59 
60     OsalGetTime(&startTick);
61     do {
62         OsalMSleep(1);
63 
64         /* time out break */
65         OsalGetTime(&endTick);
66         OsalDiffTime(&startTick, &endTick, &diffTick);
67         if ((uint32_t)(diffTick.sec * US_TO_MS_CONV + diffTick.usec / US_TO_MS_CONV) >= timeOut) {
68             break;
69         }
70     } while (true);
71 }
72 static uint32_t g_times = BEGIN_TIMES;
73 
ToGpioPeriph(uint32_t local)74 static inline uint32_t ToGpioPeriph(uint32_t local)
75 {
76     uint32_t gpioPeriph = 0;
77 
78     gpioPeriph = GPIO_REG_BASE + (local / GPIO_BIT_PER_GROUP) * GPIO_REG_STEP;
79 
80     return gpioPeriph;
81 }
82 
ToGpioPin(uint32_t local)83 static inline uint32_t ToGpioPin(uint32_t local)
84 {
85     uint32_t pinNum = 0;
86 
87     pinNum = local % GPIO_BIT_PER_GROUP;
88 
89     return (BIT(pinNum));
90 }
91 
Adc(uint32_t devNum)92 static inline uint32_t Adc(uint32_t devNum)
93 {
94     return ADC0 + devNum * ADC_REG_STEP;
95 }
96 
RcuAdc(uint32_t devNum)97 static inline uint32_t RcuAdc(uint32_t devNum)
98 {
99     return RCU_ADC0 + devNum;
100 }
101 
AdcGetData(struct AdcDeviceCntlr * adc)102 static uint16_t AdcGetData(struct AdcDeviceCntlr *adc)
103 {
104     if (adc == NULL) {
105         HDF_LOGE("%s %d: invalid param adc!", __func__, __LINE__);
106         return 0;
107     }
108     /* enable GPIOX clock */
109     rcu_periph_clock_enable(ToGpioPeriph(adc->currentPinNum));
110     /* config the GPIO as analog mode */
111     gpio_mode_set(ToGpioPeriph(adc->currentPinNum), GPIO_MODE_ANALOG, GPIO_PUPD_NONE, ToGpioPin(adc->currentPinNum));
112     /* ADC regular channel config */
113     adc_regular_channel_config(adc->regBasePhy, CHANNEL_GROUP, adc->currentChannel, ADC_SAMPLETIME_480);
114     /* ADC software trigger enable */
115     adc_software_trigger_enable(adc->regBasePhy, ADC_REGULAR_CHANNEL);
116     g_times = BEGIN_TIMES;
117     /* wait the end of conversion flag */
118     while (!adc_flag_get(adc->regBasePhy, ADC_FLAG_EOC) && g_times < TIME_OUT) {
119         g_times++;
120     };
121     /* clear the end of conversion flag */
122     adc_flag_clear(adc->regBasePhy, ADC_FLAG_EOC);
123     /* return regular channel sample value */
124     return adc_regular_data_read(adc->regBasePhy);
125 }
126 
AdcDevRead(struct AdcDevice * device,uint8_t channel,uint32_t * val)127 static int32_t AdcDevRead(struct AdcDevice *device, uint8_t channel, uint32_t *val)
128 {
129     int ret = HDF_FAILURE;
130     struct AdcDeviceCntlr *adc = NULL;
131 
132     if (device == NULL) {
133         HDF_LOGE("%s %d: device is null!", __func__, __LINE__);
134         return HDF_ERR_INVALID_PARAM;
135     }
136 
137     adc = (struct AdcDeviceCntlr *)device;
138     for (int i = 0; i < adc->channelNums; i++) {
139         if (channel == adc->validChannels[i]) {
140             adc->currentChannel = adc->validChannels[i];
141             adc->currentPinNum = adc->outputPinNums[i];
142             ret = HDF_SUCCESS;
143             break;
144         }
145     }
146     if (ret != HDF_SUCCESS) {
147         HDF_LOGE("%s %d: invalid channel number:%d", __func__, __LINE__, channel);
148         return HDF_ERR_INVALID_PARAM;
149     }
150 
151     *val = (uint32_t)AdcGetData(adc);
152     if (g_times == TIME_OUT) {
153         HDF_LOGE("%s %d:data read out of time!", __func__, __LINE__);
154         return HDF_ERR_TIMEOUT;
155     }
156 
157     return HDF_SUCCESS;
158 }
159 
AdcDevStop(struct AdcDevice * device)160 static int32_t AdcDevStop(struct AdcDevice *device)
161 {
162     if (device == NULL) {
163         HDF_LOGE("%s %d: device is null!", __func__, __LINE__);
164         return HDF_ERR_INVALID_PARAM;
165     }
166     /* reset ADC */
167     adc_deinit();
168 
169     return HDF_SUCCESS;
170 }
171 
AdcDevStart(struct AdcDevice * device)172 static int32_t AdcDevStart(struct AdcDevice *device)
173 {
174     if (device == NULL) {
175         HDF_LOGE("%s %d: device is null!", __func__, __LINE__);
176         return HDF_ERR_INVALID_PARAM;
177     }
178     struct AdcDeviceCntlr *adc = NULL;
179     adc = (struct AdcDeviceCntlr *)device;
180     /* enable ADC clock */
181     rcu_periph_clock_enable(RcuAdc(adc->deviceNum));
182     /* config ADC clock */
183     adc_clock_config(ADC_ADCCK_PCLK2_DIV8);
184     /* reset ADC */
185     adc_deinit();
186     /* ADC mode config */
187     adc_sync_mode_config(ADC_SYNC_MODE_INDEPENDENT);
188     /* ADC contineous function disable */
189     adc_special_function_config(adc->regBasePhy, ADC_CONTINUOUS_MODE, DISABLE);
190     /* ADC scan mode disable */
191     adc_special_function_config(adc->regBasePhy, ADC_SCAN_MODE, DISABLE);
192     /* ADC data alignment config */
193     adc_data_alignment_config(adc->regBasePhy, ADC_DATAALIGN_RIGHT);
194     /* ADC channel length config */
195     adc_channel_length_config(adc->regBasePhy, ADC_REGULAR_CHANNEL, CHANNEL_LENGTH);
196     /* ADC trigger config */
197     adc_external_trigger_source_config(adc->regBasePhy, ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_T0_CH0);
198     adc_external_trigger_config(adc->regBasePhy, ADC_REGULAR_CHANNEL, EXTERNAL_TRIGGER_DISABLE);
199     /* enable ADC interface */
200     adc_enable(adc->regBasePhy);
201     AdcMDelay(DELAY_TIME_MS);
202     /* ADC calibration and reset calibration */
203     adc_calibration_enable(adc->regBasePhy);
204     return HDF_SUCCESS;
205 }
206 
207 static const struct AdcMethod g_method = {
208     .read = AdcDevRead,
209     .stop = AdcDevStop,
210     .start = AdcDevStart,
211 };
212 
213 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
214 #define ADC_FIND_CONFIG(node, name, adc)                                                                               \
215     do {                                                                                                               \
216         if (strcmp(HCS_PROP(node, match_attr), name) == 0) {                                                           \
217             uint32_t deviceNum = HCS_PROP(node, deviceNum);                                                            \
218             uint8_t channelNums = HCS_PROP(node, channelNums);                                                         \
219             uint8_t validChannels[] = HCS_ARRAYS(HCS_NODE(node, validChannels));                                       \
220             uint32_t outputPinNums[] = HCS_ARRAYS(HCS_NODE(node, outputPinNums));                                      \
221             adc->deviceNum = deviceNum;                                                                                \
222             adc->channelNums = channelNums;                                                                            \
223             for (int i = 0; i < channelNums; i++) {                                                                    \
224                 adc->validChannels[i] = validChannels[i];                                                              \
225                 adc->outputPinNums[i] = outputPinNums[i];                                                              \
226             }                                                                                                          \
227             result = HDF_SUCCESS;                                                                                      \
228         }                                                                                                              \
229     } while (0)
230 #define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform)
231 #define PLATFORM_ADC_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), adc_config)
AdcReadDrs(struct AdcDeviceCntlr * adc,const char * deviceMatchAttr)232 static int32_t AdcReadDrs(struct AdcDeviceCntlr *adc, const char *deviceMatchAttr)
233 {
234     int32_t result = HDF_FAILURE;
235     if (adc == NULL || deviceMatchAttr == NULL) {
236         HDF_LOGE("%s %d: device or deviceMatchAttr is NULL", __func__, __LINE__);
237         return HDF_ERR_INVALID_PARAM;
238     }
239 
240 #if HCS_NODE_HAS_PROP(PLATFORM_CONFIG, adc_config)
241     HCS_FOREACH_CHILD_VARGS(PLATFORM_ADC_CONFIG, ADC_FIND_CONFIG, deviceMatchAttr, adc);
242 #endif
243     if (result != HDF_SUCCESS) {
244         HDF_LOGE("resourceNode %s is NULL\r\n", deviceMatchAttr);
245     }
246     return result;
247 }
248 #else
AdcReadDrs(struct AdcDeviceCntlr * adc,struct DeviceResourceNode * node)249 static int32_t AdcReadDrs(struct AdcDeviceCntlr *adc, struct DeviceResourceNode *node)
250 {
251     int32_t ret = HDF_SUCCESS;
252     struct DeviceResourceIface *drsOps = NULL;
253     if (adc == NULL || node == NULL) {
254         HDF_LOGE("%s %d: AdcDeviceCntlr or DeviceResourceNode is null!", __func__, __LINE__);
255         return HDF_ERR_INVALID_PARAM;
256     }
257 
258     drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
259     if (drsOps == NULL || drsOps->GetUint32 == NULL) {
260         HDF_LOGE("%s %d: invalid drs ops fail!", __func__, __LINE__);
261         return HDF_FAILURE;
262     }
263 
264     ret = drsOps->GetUint32(node, "deviceNum", &adc->deviceNum, 0);
265     if (ret != HDF_SUCCESS) {
266         HDF_LOGE("%s %d: read deviceNum fail!", __func__, __LINE__);
267         return ret;
268     }
269 
270     ret = drsOps->GetUint8(node, "channelNums", &adc->channelNums, 0);
271     if (ret != HDF_SUCCESS) {
272         HDF_LOGE("%s %d: read channelNums fail!", __func__, __LINE__);
273         return ret;
274     }
275 
276     ret = drsOps->GetUint8Array(node, "validChannels", adc->validChannels, adc->channelNums, 0);
277     if (ret != HDF_SUCCESS) {
278         HDF_LOGE("%s %d: read validChannels fail!", __func__, __LINE__);
279         return ret;
280     }
281 
282     ret = drsOps->GetUint32Array(node, "outputPinNums", &adc->outputPinNums, adc->channelNums, 0);
283     if (ret != HDF_SUCCESS) {
284         HDF_LOGE("%s %d: read outputPinNums fail!", __func__, __LINE__);
285         return ret;
286     }
287     adc->currentChannel = 0;
288     adc->currentPinNum = 0;
289     return HDF_SUCCESS;
290 }
291 #endif
292 
AdcParseInit(struct HdfDeviceObject * device)293 static int32_t AdcParseInit(struct HdfDeviceObject *device)
294 {
295     int32_t ret = HDF_SUCCESS;
296     struct AdcDeviceCntlr *adc = NULL;
297     adc = (struct AdcDeviceCntlr *)OsalMemCalloc(sizeof(*adc));
298     do {
299         if (adc == NULL) {
300             HDF_LOGE("%s %d: malloc AdcDeviceCntlr failed!", __func__, __LINE__);
301             ret = HDF_ERR_MALLOC_FAIL;
302             break;
303         }
304         HDF_LOGI("%s: Enter", __func__);
305 
306 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
307         if (device == NULL || device->deviceMatchAttr == NULL) {
308             HDF_LOGE("%s %d: device or device->deviceMatchAttr is null !", __func__, __LINE__);
309             ret = HDF_ERR_INVALID_OBJECT;
310             break;
311         }
312         ret = AdcReadDrs(adc, device->deviceMatchAttr);
313 #else
314         if (device == NULL || device->property == NULL) {
315             HDF_LOGE("%s %d: device or device->property is null !", __func__, __LINE__);
316             ret = HDF_ERR_INVALID_OBJECT;
317             break;
318         }
319         ret = AdcReadDrs(adc, device->property);
320 #endif
321         if (ret != HDF_SUCCESS) {
322             HDF_LOGE("%s %d: adc read failed!", __func__, __LINE__);
323             break;
324         }
325         adc->regBasePhy = Adc(adc->deviceNum);
326         adc->device.priv = (void *)adc;
327         adc->device.devNum = adc->deviceNum;
328         adc->device.ops = &g_method;
329         ret = AdcDeviceAdd(&adc->device);
330         if (ret != HDF_SUCCESS) {
331             HDF_LOGE("%s %d: adc device add failed!", __func__, __LINE__);
332             break;
333         }
334         HDF_LOGI("%s: adc%d init success", __func__, adc->deviceNum);
335         return HDF_SUCCESS;
336     } while (0);
337 
338     if (adc != NULL) {
339         AdcDeviceRemove(&adc->device);
340         OsalMemFree(adc);
341         OsalMemFree(adc->validChannels);
342         OsalMemFree(adc->outputPinNums);
343     }
344     return ret;
345 }
346 
AdcInit(struct HdfDeviceObject * device)347 static int32_t AdcInit(struct HdfDeviceObject *device)
348 {
349     int32_t ret;
350     if (device == NULL) {
351         HDF_LOGE("%s %d: device node is null!", __func__, __LINE__);
352         return HDF_ERR_INVALID_PARAM;
353     }
354 
355     ret = AdcParseInit(device);
356     if (ret != HDF_SUCCESS) {
357         HDF_LOGE("%s %d: adc parse init failed!", __func__, __LINE__);
358     }
359     return ret;
360 }
361 
362 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
AdcRemoveByObject(const struct HdfDeviceObject * device)363 static void AdcRemoveByObject(const struct HdfDeviceObject *device)
364 {
365     struct AdcDevice *adcDev = NULL;
366     struct AdcDeviceCntlr *adc = NULL;
367 
368     if (device == NULL) {
369         HDF_LOGE("%s %d: device is NULL", __func__, __LINE__);
370         return;
371     }
372 
373     adcDev = device->priv;
374     if (adcDev == NULL) {
375         HDF_LOGE("%s %d: device priv is NULL\r\n", __func__, __LINE__);
376         return;
377     }
378 
379     AdcDevicePut(adcDev);
380     AdcDeviceRemove(adcDev);
381     adc = (struct AdcDeviceCntlr *)adcDev;
382     OsalMemFree(adcDev);
383 }
384 #else
AdcRemoveByNode(const struct DeviceResourceNode * node)385 static void AdcRemoveByNode(const struct DeviceResourceNode *node)
386 {
387     int32_t ret;
388     int32_t deviceNum;
389     struct AdcDevice *device = NULL;
390     struct AdcDeviceCntlr *adc = NULL;
391     struct DeviceResourceIface *drsOps = NULL;
392 
393     drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
394 
395     ret = drsOps->GetUint32(node, "deviceNum", (uint32_t *)&deviceNum, 0);
396     if (ret != HDF_SUCCESS) {
397         HDF_LOGE("%s %d: get resouce failed!", __func__, __LINE__);
398         return ret;
399     }
400     device = AdcDeviceGet(deviceNum);
401     if (device != NULL && device->priv == node) {
402         AdcDevicePut(device);
403         AdcDeviceRemove(device);
404         adc = (struct AdcDeviceCntlr *)device;
405         OsalMemFree(adc);
406     }
407 }
408 #endif
409 
AdcRelease(struct HdfDeviceObject * device)410 static void AdcRelease(struct HdfDeviceObject *device)
411 {
412 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
413     AdcRemoveByObject(device);
414 #else
415     AdcRemoveByNode(device->property);
416 #endif
417 }
418 
419 static struct HdfDriverEntry g_AdcDriverEntry = {
420     .moduleVersion = 1,
421     .Init = AdcInit,
422     .Release = AdcRelease,
423     .moduleName = "GD_ADC_MODULE_HDF",
424 };
425 
426 HDF_INIT(g_AdcDriverEntry);