• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "adc_core.h"
10 #include "hdf_device_desc.h"
11 #include "hdf_log.h"
12 #include "osal_mem.h"
13 #include "osal_spinlock.h"
14 #include "osal_time.h"
15 #include "platform_core.h"
16 #include "platform_trace.h"
17 
18 #define HDF_LOG_TAG adc_core_c
19 #define ADC_TRACE_BASIC_PARAM_NUM  2
20 #define ADC_TRACE_PARAM_STOP_NUM   2
21 
22 #define ADC_HANDLE_SHIFT    0xFF00U
23 
24 struct AdcManager {
25     struct IDeviceIoService service;
26     struct HdfDeviceObject *device;
27     struct AdcDevice *devices[ADC_DEVICES_MAX];
28     OsalSpinlock spin;
29 };
30 
31 static struct AdcManager *g_adcManager = NULL;
32 
AdcDeviceLockDefault(struct AdcDevice * device)33 static int32_t AdcDeviceLockDefault(struct AdcDevice *device)
34 {
35     if (device == NULL) {
36         HDF_LOGE("AdcDeviceLockDefault: device is null!");
37         return HDF_ERR_INVALID_OBJECT;
38     }
39     return OsalSpinLock(&device->spin);
40 }
41 
AdcDeviceUnlockDefault(struct AdcDevice * device)42 static void AdcDeviceUnlockDefault(struct AdcDevice *device)
43 {
44     if (device == NULL) {
45         HDF_LOGE("AdcDeviceUnlockDefault: device is null!");
46         return;
47     }
48     (void)OsalSpinUnlock(&device->spin);
49 }
50 
51 static const struct AdcLockMethod g_adcLockOpsDefault = {
52     .lock = AdcDeviceLockDefault,
53     .unlock = AdcDeviceUnlockDefault,
54 };
55 
AdcDeviceLock(struct AdcDevice * device)56 static inline int32_t AdcDeviceLock(struct AdcDevice *device)
57 {
58     if (device->lockOps == NULL || device->lockOps->lock == NULL) {
59         HDF_LOGE("AdcDeviceLock: adc device lock is not support!");
60         return HDF_ERR_NOT_SUPPORT;
61     }
62     return device->lockOps->lock(device);
63 }
64 
AdcDeviceUnlock(struct AdcDevice * device)65 static inline void AdcDeviceUnlock(struct AdcDevice *device)
66 {
67     if (device->lockOps != NULL && device->lockOps->unlock != NULL) {
68         device->lockOps->unlock(device);
69     }
70 }
71 
AdcDeviceStart(struct AdcDevice * device)72 int32_t AdcDeviceStart(struct AdcDevice *device)
73 {
74     int32_t ret;
75 
76     if (device == NULL) {
77         HDF_LOGE("AdcDeviceStart: device is null!");
78         return HDF_ERR_INVALID_OBJECT;
79     }
80 
81     if (device->ops == NULL || device->ops->start == NULL) {
82         HDF_LOGE("AdcDeviceStart: ops or start is null!");
83         return HDF_ERR_NOT_SUPPORT;
84     }
85 
86     if (AdcDeviceLock(device) != HDF_SUCCESS) {
87         HDF_LOGE("AdcDeviceStart: lock adc device fail!");
88         return HDF_ERR_DEVICE_BUSY;
89     }
90 
91     ret = device->ops->start(device);
92     if (PlatformTraceStart() == HDF_SUCCESS) {
93         unsigned int infos[ADC_TRACE_BASIC_PARAM_NUM];
94         infos[PLATFORM_TRACE_UINT_PARAM_SIZE_1 - 1] = device->devNum;
95         infos[PLATFORM_TRACE_UINT_PARAM_SIZE_2 - 1] = device->chanNum;
96         PlatformTraceAddUintMsg(PLATFORM_TRACE_MODULE_ADC, PLATFORM_TRACE_MODULE_ADC_FUN_START,
97             infos, ADC_TRACE_BASIC_PARAM_NUM);
98         PlatformTraceStop();
99     }
100     AdcDeviceUnlock(device);
101     return ret;
102 }
103 
AdcDeviceStop(struct AdcDevice * device)104 int32_t AdcDeviceStop(struct AdcDevice *device)
105 {
106     int32_t ret;
107 
108     if (device == NULL) {
109         HDF_LOGE("AdcDeviceStop: device is null!");
110         return HDF_ERR_INVALID_OBJECT;
111     }
112 
113     if (device->ops == NULL || device->ops->stop == NULL) {
114         HDF_LOGE("AdcDeviceStop: ops or stop is null!");
115         return HDF_ERR_NOT_SUPPORT;
116     }
117 
118     if (AdcDeviceLock(device) != HDF_SUCCESS) {
119         HDF_LOGE("AdcDeviceStop: lock adc device fail!");
120         return HDF_ERR_DEVICE_BUSY;
121     }
122 
123     ret = device->ops->stop(device);
124     if (PlatformTraceStart() == HDF_SUCCESS) {
125         unsigned int infos[ADC_TRACE_PARAM_STOP_NUM];
126         infos[PLATFORM_TRACE_UINT_PARAM_SIZE_1 - 1] = device->devNum;
127         infos[PLATFORM_TRACE_UINT_PARAM_SIZE_2 - 1] = device->chanNum;
128         PlatformTraceAddUintMsg(PLATFORM_TRACE_MODULE_ADC, PLATFORM_TRACE_MODULE_ADC_FUN_STOP,
129             infos, ADC_TRACE_PARAM_STOP_NUM);
130         PlatformTraceStop();
131         PlatformTraceInfoDump();
132     }
133     AdcDeviceUnlock(device);
134     return ret;
135 }
136 
AdcManagerAddDevice(struct AdcDevice * device)137 static int32_t AdcManagerAddDevice(struct AdcDevice *device)
138 {
139     int32_t ret;
140     struct AdcManager *manager = g_adcManager;
141 
142     if (device->devNum >= ADC_DEVICES_MAX) {
143         HDF_LOGE("AdcManagerAddDevice: devNum:%u exceed!", device->devNum);
144         return HDF_ERR_INVALID_OBJECT;
145     }
146 
147     if (manager == NULL) {
148         HDF_LOGE("AdcManagerAddDevice: get adc manager fail!");
149         return HDF_ERR_NOT_SUPPORT;
150     }
151 
152     if (OsalSpinLockIrq(&manager->spin) != HDF_SUCCESS) {
153         HDF_LOGE("AdcManagerAddDevice: lock adc manager fail!");
154         return HDF_ERR_DEVICE_BUSY;
155     }
156 
157     if (manager->devices[device->devNum] != NULL) {
158         HDF_LOGE("AdcManagerAddDevice: adc device num:%u already exits!", device->devNum);
159         ret = HDF_FAILURE;
160     } else {
161         manager->devices[device->devNum] = device;
162         ret = HDF_SUCCESS;
163     }
164 
165     (void)OsalSpinUnlockIrq(&manager->spin);
166     return ret;
167 }
168 
AdcManagerRemoveDevice(struct AdcDevice * device)169 static void AdcManagerRemoveDevice(struct AdcDevice *device)
170 {
171     struct AdcManager *manager = g_adcManager;
172 
173     if (device->devNum < 0 || device->devNum >= ADC_DEVICES_MAX) {
174         HDF_LOGE("AdcManagerRemoveDevice: invalid devNum:%u!", device->devNum);
175         return;
176     }
177 
178     if (manager == NULL) {
179         HDF_LOGE("AdcManagerRemoveDevice: get adc manager fail!");
180         return;
181     }
182 
183     if (OsalSpinLockIrq(&manager->spin) != HDF_SUCCESS) {
184         HDF_LOGE("AdcManagerRemoveDevice: lock adc manager fail!");
185         return;
186     }
187 
188     if (manager->devices[device->devNum] != device) {
189         HDF_LOGE("AdcManagerRemoveDevice: adc device(%u) not in manager!", device->devNum);
190     } else {
191         manager->devices[device->devNum] = NULL;
192     }
193 
194     (void)OsalSpinUnlockIrq(&manager->spin);
195 }
196 
AdcManagerFindDevice(uint32_t number)197 static struct AdcDevice *AdcManagerFindDevice(uint32_t number)
198 {
199     struct AdcDevice *device = NULL;
200     struct AdcManager *manager = g_adcManager;
201 
202     if (number >= ADC_DEVICES_MAX) {
203         HDF_LOGE("AdcManagerFindDevice: invalid devNum:%u!", number);
204         return NULL;
205     }
206 
207     if (manager == NULL) {
208         HDF_LOGE("AdcManagerFindDevice: get adc manager fail!");
209         return NULL;
210     }
211 
212     if (OsalSpinLockIrq(&manager->spin) != HDF_SUCCESS) {
213         HDF_LOGE("AdcManagerFindDevice: lock adc manager fail!");
214         return NULL;
215     }
216 
217     device = manager->devices[number];
218     (void)OsalSpinUnlockIrq(&manager->spin);
219 
220     return device;
221 }
222 
AdcDeviceGet(uint32_t number)223 struct AdcDevice *AdcDeviceGet(uint32_t number)
224 {
225     return AdcManagerFindDevice(number);
226 }
227 
AdcDevicePut(struct AdcDevice * device)228 void AdcDevicePut(struct AdcDevice *device)
229 {
230     (void)device;
231 }
232 
AdcDeviceOpen(uint32_t number)233 static struct AdcDevice *AdcDeviceOpen(uint32_t number)
234 {
235     int32_t ret;
236     struct AdcDevice *device = NULL;
237 
238     device = AdcDeviceGet(number);
239     if (device == NULL) {
240         HDF_LOGE("AdcDeviceOpen: get adc device fail!");
241         return NULL;
242     }
243 
244     ret = AdcDeviceStart(device);
245     if (ret != HDF_SUCCESS) {
246         HDF_LOGE("AdcDeviceOpen: start adc device fail!");
247         return NULL;
248     }
249 
250     return device;
251 }
252 
AdcDeviceClose(struct AdcDevice * device)253 static void AdcDeviceClose(struct AdcDevice *device)
254 {
255     if (device == NULL) {
256         HDF_LOGE("AdcDeviceClose: close adc device fail!");
257         return;
258     }
259 
260     (void)AdcDeviceStop(device);
261     AdcDevicePut(device);
262 }
263 
AdcDeviceAdd(struct AdcDevice * device)264 int32_t AdcDeviceAdd(struct AdcDevice *device)
265 {
266     int32_t ret;
267 
268     if (device == NULL) {
269         HDF_LOGE("AdcDeviceAdd: device is null!");
270         return HDF_ERR_INVALID_OBJECT;
271     }
272 
273     if (device->ops == NULL) {
274         HDF_LOGE("AdcDeviceAdd: no ops supplied!");
275         return HDF_ERR_INVALID_OBJECT;
276     }
277 
278     if (device->lockOps == NULL) {
279         HDF_LOGI("AdcDeviceAdd: use default lockOps!");
280         device->lockOps = &g_adcLockOpsDefault;
281     }
282 
283     if (OsalSpinInit(&device->spin) != HDF_SUCCESS) {
284         HDF_LOGE("AdcDeviceAdd: init lock fail!");
285         return HDF_FAILURE;
286     }
287 
288     ret = AdcManagerAddDevice(device);
289     if (ret != HDF_SUCCESS) {
290         HDF_LOGE("AdcDeviceAdd: adc manager add device fail!");
291         (void)OsalSpinDestroy(&device->spin);
292     }
293     return ret;
294 }
295 
AdcDeviceRemove(struct AdcDevice * device)296 void AdcDeviceRemove(struct AdcDevice *device)
297 {
298     if (device == NULL) {
299         HDF_LOGE("AdcDeviceRemove: device is null!");
300         return;
301     }
302     AdcManagerRemoveDevice(device);
303     (void)OsalSpinDestroy(&device->spin);
304 }
305 
AdcDeviceRead(struct AdcDevice * device,uint32_t channel,uint32_t * val)306 int32_t AdcDeviceRead(struct AdcDevice *device, uint32_t channel, uint32_t *val)
307 {
308     int32_t ret;
309 
310     if (device == NULL) {
311         HDF_LOGE("AdcDeviceRead: device is null!");
312         return HDF_ERR_INVALID_OBJECT;
313     }
314 
315     if (device->ops == NULL || device->ops->read == NULL) {
316         HDF_LOGE("AdcDeviceRead: ops or read is null!");
317         return HDF_ERR_NOT_SUPPORT;
318     }
319 
320     if (val == NULL) {
321         HDF_LOGE("AdcDeviceRead: invalid val pointer!");
322         return HDF_ERR_INVALID_PARAM;
323     }
324 
325     if (AdcDeviceLock(device) != HDF_SUCCESS) {
326         HDF_LOGE("AdcDeviceRead: lock adc device fail!");
327         return HDF_ERR_DEVICE_BUSY;
328     }
329 
330     ret = device->ops->read(device, channel, val);
331     AdcDeviceUnlock(device);
332     return ret;
333 }
334 
AdcManagerIoOpen(struct HdfSBuf * data,struct HdfSBuf * reply)335 static int32_t AdcManagerIoOpen(struct HdfSBuf *data, struct HdfSBuf *reply)
336 {
337     uint32_t number;
338 
339     if (data == NULL || reply == NULL) {
340         HDF_LOGE("AdcManagerIoOpen: invalid data or reply!");
341         return HDF_ERR_INVALID_PARAM;
342     }
343 
344     if (!HdfSbufReadUint32(data, &number)) {
345         HDF_LOGE("AdcManagerIoOpen: read number fail!");
346         return HDF_ERR_IO;
347     }
348 
349     if (number >= ADC_DEVICES_MAX) {
350         HDF_LOGE("AdcManagerIoOpen: invalid number!");
351         return HDF_ERR_INVALID_PARAM;
352     }
353 
354     if (AdcDeviceOpen(number) == NULL) {
355         HDF_LOGE("AdcManagerIoOpen: get device %u fail!", number);
356         return HDF_ERR_NOT_SUPPORT;
357     }
358 
359     number = (uint32_t)(number + ADC_HANDLE_SHIFT);
360     if (!HdfSbufWriteUint32(reply, (uint32_t)(uintptr_t)number)) {
361         HDF_LOGE("AdcManagerIoOpen: write number fail!");
362         return HDF_ERR_IO;
363     }
364 
365     return HDF_SUCCESS;
366 }
367 
AdcManagerIoClose(struct HdfSBuf * data,struct HdfSBuf * reply)368 static int32_t AdcManagerIoClose(struct HdfSBuf *data, struct HdfSBuf *reply)
369 {
370     uint32_t number;
371 
372     (void)reply;
373     if (data == NULL) {
374         HDF_LOGE("AdcManagerIoClose: invalid data!");
375         return HDF_ERR_INVALID_PARAM;
376     }
377 
378     if (!HdfSbufReadUint32(data, &number)) {
379         HDF_LOGE("AdcManagerIoClose: read number fail!");
380         return HDF_ERR_IO;
381     }
382 
383     number = (uint32_t)(number - ADC_HANDLE_SHIFT);
384     if (number >= ADC_DEVICES_MAX) {
385         HDF_LOGE("AdcManagerIoClose: get device %u fail!", number);
386         return HDF_ERR_INVALID_PARAM;
387     }
388 
389     AdcDeviceClose(AdcManagerFindDevice(number));
390     return HDF_SUCCESS;
391 }
392 
AdcManagerIoRead(struct HdfSBuf * data,struct HdfSBuf * reply)393 static int32_t AdcManagerIoRead(struct HdfSBuf *data, struct HdfSBuf *reply)
394 {
395     int32_t ret;
396     uint32_t number;
397     uint32_t channel;
398     uint32_t val;
399 
400     if (data == NULL || reply == NULL) {
401         HDF_LOGE("AdcManagerIoRead: invalid data or reply!");
402         return HDF_ERR_INVALID_PARAM;
403     }
404 
405     if (!HdfSbufReadUint32(data, &number)) {
406         HDF_LOGE("AdcManagerIoRead: read number fail!");
407         return HDF_ERR_IO;
408     }
409 
410     if (!HdfSbufReadUint32(data, &channel)) {
411         HDF_LOGE("AdcManagerIoRead: read channel fail!");
412         return HDF_ERR_IO;
413     }
414 
415     number  = (uint32_t)(number - ADC_HANDLE_SHIFT);
416     ret = AdcDeviceRead(AdcManagerFindDevice(number), channel, &val);
417     if (ret != HDF_SUCCESS) {
418         HDF_LOGE("AdcManagerIoRead: read val fail!");
419         return HDF_ERR_IO;
420     }
421 
422     if (!HdfSbufWriteUint32(reply, val)) {
423         HDF_LOGE("AdcManagerIoRead: write val fail!");
424         return HDF_ERR_IO;
425     }
426 
427     return ret;
428 }
429 
AdcManagerDispatch(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)430 static int32_t AdcManagerDispatch(struct HdfDeviceIoClient *client, int cmd,
431     struct HdfSBuf *data, struct HdfSBuf *reply)
432 {
433     (void)client;
434     switch (cmd) {
435         case ADC_IO_OPEN:
436             return AdcManagerIoOpen(data, reply);
437         case ADC_IO_CLOSE:
438             return AdcManagerIoClose(data, reply);
439         case ADC_IO_READ:
440             return AdcManagerIoRead(data, reply);
441         default:
442             HDF_LOGE("AdcManagerDispatch: cmd %d is not support!", cmd);
443             return HDF_ERR_NOT_SUPPORT;
444     }
445     return HDF_SUCCESS;
446 }
447 
AdcManagerBind(struct HdfDeviceObject * device)448 static int32_t AdcManagerBind(struct HdfDeviceObject *device)
449 {
450     (void)device;
451     return HDF_SUCCESS;
452 }
453 
AdcManagerInit(struct HdfDeviceObject * device)454 static int32_t AdcManagerInit(struct HdfDeviceObject *device)
455 {
456     int32_t ret;
457     struct AdcManager *manager = NULL;
458 
459     HDF_LOGI("AdcManagerInit: enter!");
460     if (device == NULL) {
461         HDF_LOGE("AdcManagerInit: device is null!");
462         return HDF_ERR_INVALID_OBJECT;
463     }
464 
465     manager = (struct AdcManager *)OsalMemCalloc(sizeof(*manager));
466     if (manager == NULL) {
467         HDF_LOGE("AdcManagerInit: memcalloc for manager fail!");
468         return HDF_ERR_MALLOC_FAIL;
469     }
470 
471     ret = OsalSpinInit(&manager->spin);
472     if (ret != HDF_SUCCESS) {
473         HDF_LOGE("AdcManagerInit: spinlock init fail!");
474         OsalMemFree(manager);
475         return HDF_FAILURE;
476     }
477 
478     manager->device = device;
479     g_adcManager = manager;
480     device->service = &manager->service;
481     device->service->Dispatch = AdcManagerDispatch;
482     return HDF_SUCCESS;
483 }
484 
AdcManagerRelease(struct HdfDeviceObject * device)485 static void AdcManagerRelease(struct HdfDeviceObject *device)
486 {
487     struct AdcManager *manager = NULL;
488 
489     HDF_LOGI("AdcManagerRelease: enter!");
490     if (device == NULL) {
491         HDF_LOGE("AdcManagerRelease: device is null!");
492         return;
493     }
494 
495     manager = (struct AdcManager *)device->service;
496     if (manager == NULL) {
497         HDF_LOGI("AdcManagerRelease: no service bind!");
498         return;
499     }
500 
501     g_adcManager = NULL;
502     OsalMemFree(manager);
503 }
504 
505 struct HdfDriverEntry g_adcManagerEntry = {
506     .moduleVersion = 1,
507     .Bind = AdcManagerBind,
508     .Init = AdcManagerInit,
509     .Release = AdcManagerRelease,
510     .moduleName = "HDF_PLATFORM_ADC_MANAGER",
511 };
512 HDF_INIT(g_adcManagerEntry);
513