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