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);