• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * adc driver adapter of linux
3  *
4  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
5  *
6  * This software is licensed under the terms of the GNU General Public
7  * License version 2, as published by the Free Software Foundation, and
8  * may be copied, distributed, and modified under those terms.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  */
16 
17 #include <linux/fs.h>
18 #include <linux/kernel.h>
19 #include "device_resource_if.h"
20 #include "hdf_base.h"
21 #include "hdf_device_desc.h"
22 #include "hdf_log.h"
23 #include "osal_mem.h"
24 #include "securec.h"
25 #include "adc_core.h"
26 
27 #define ADC_STRING_VALUE_LEN 15
28 #define ADC_MAX_CHANNEL_NUM 128
29 #define ADC_CHANNEL_NAME_LEN 30
30 #define INT_MAX_VALUE 2147483647
31 #define FILE_MODE 0600
32 #define DECIMAL_SHIFT_LEFT 10
33 
34 struct AdcIioDevice {
35     struct AdcDevice device;
36     uint32_t channelNum;
37     volatile unsigned char *regBase;
38     volatile unsigned char *pinCtrlBase;
39     uint32_t regBasePhy;
40     uint32_t regSize;
41     uint32_t deviceNum;
42     uint32_t dataWidth;
43     uint32_t validChannel;
44     uint32_t scanMode;
45     uint32_t delta;
46     uint32_t deglitch;
47     uint32_t glitchSample;
48     uint32_t rate;
49     const char *driverPathname[ADC_MAX_CHANNEL_NUM];
50     struct file *fp[ADC_MAX_CHANNEL_NUM];
51 };
52 
AdcIioRead(struct AdcDevice * device,uint32_t channel,uint32_t * val)53 static int32_t AdcIioRead(struct AdcDevice *device, uint32_t channel, uint32_t *val)
54 {
55     int ret;
56     loff_t pos = 0;
57     unsigned char strValue[ADC_STRING_VALUE_LEN] = {0};
58     struct AdcIioDevice *adcDevice = NULL;
59 
60     if (device == NULL) {
61         HDF_LOGE("AdcIioRead: device is null!");
62         return HDF_ERR_INVALID_OBJECT;
63     }
64     if (val == NULL) {
65         HDF_LOGE("AdcIioRead: val is null!");
66         return HDF_ERR_INVALID_PARAM;
67     }
68     adcDevice = (struct AdcIioDevice *)device;
69     if (channel >= adcDevice->channelNum || adcDevice->fp[channel] == NULL) {
70         HDF_LOGE("AdcIioRead: invalid channel:%u!", channel);
71         return HDF_ERR_INVALID_PARAM;
72     }
73     ret = kernel_read(adcDevice->fp[channel], strValue, ADC_STRING_VALUE_LEN, &pos);
74     if (ret < 0) {
75         HDF_LOGE("AdcIioRead: kernel_read fail, ret: %d!", ret);
76         return HDF_PLT_ERR_OS_API;
77     }
78     *val = simple_strtoul(strValue, NULL, 0);
79     return HDF_SUCCESS;
80 }
81 
AdcIioStop(struct AdcDevice * device)82 static int32_t AdcIioStop(struct AdcDevice *device)
83 {
84     int ret;
85     uint32_t i;
86     struct AdcIioDevice *adcDevice = NULL;
87 
88     if (device == NULL) {
89         HDF_LOGE("AdcIioStop: device is null!");
90         return HDF_ERR_INVALID_OBJECT;
91     }
92     adcDevice = (struct AdcIioDevice *)device;
93     for (i = 0; i < adcDevice->channelNum; i++) {
94         if (adcDevice->fp[i] != NULL) {
95             ret = filp_close(adcDevice->fp[i], NULL);
96             if (ret != 0) {
97                 HDF_LOGE("AdcIioStop: filp_close fail!");
98                 adcDevice->fp[i] = NULL;
99                 return HDF_FAILURE;
100             }
101             adcDevice->fp[i] = NULL;
102         }
103     }
104     return HDF_SUCCESS;
105 }
106 
AdcIioStart(struct AdcDevice * device)107 static int32_t AdcIioStart(struct AdcDevice *device)
108 {
109     uint32_t i;
110     int32_t ret;
111     struct AdcIioDevice *adcDevice = NULL;
112 
113     if (device == NULL) {
114         HDF_LOGE("AdcIioStart: device is null!");
115         return HDF_ERR_INVALID_OBJECT;
116     }
117     adcDevice = (struct AdcIioDevice *)device;
118     for (i = 0; i < adcDevice->channelNum; i++) {
119         if (adcDevice->fp[i] != NULL) {
120             continue;
121         }
122         adcDevice->fp[i] = filp_open(adcDevice->driverPathname[i], O_RDWR | O_NOCTTY | O_NDELAY, FILE_MODE);
123         if (IS_ERR(adcDevice->fp[i])) {
124             adcDevice->fp[i] = NULL;
125             ret = AdcIioStop(device);
126             if (ret != HDF_SUCCESS) {
127                 return ret;
128             }
129             HDF_LOGE("AdcIioStart: filp open fail!");
130             return HDF_PLT_ERR_OS_API;
131         }
132     }
133 
134     return HDF_SUCCESS;
135 }
136 static const struct AdcMethod g_method = {
137     .read = AdcIioRead,
138     .stop = AdcIioStop,
139     .start = AdcIioStart,
140 };
141 
AdcIioReadDrs(struct AdcIioDevice * adcDevice,const struct DeviceResourceNode * node)142 static int32_t AdcIioReadDrs(struct AdcIioDevice *adcDevice, const struct DeviceResourceNode *node)
143 {
144     int32_t ret;
145     const char *drName = NULL;
146     char channelName[ADC_CHANNEL_NAME_LEN] = {0};
147     struct DeviceResourceIface *drsOps = NULL;
148     uint32_t i;
149 
150     drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
151     if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetString == NULL) {
152         HDF_LOGE("AdcIioReadDrs: invalid drs ops!");
153         return HDF_ERR_NOT_SUPPORT;
154     }
155     ret = drsOps->GetUint32(node, "deviceNum", &adcDevice->deviceNum, 0);
156     if (ret != HDF_SUCCESS) {
157         HDF_LOGE("AdcIioReadDrs: read deviceNum fail, ret: %d!", ret);
158         return ret;
159     }
160     ret = drsOps->GetUint32(node, "channelNum", &adcDevice->channelNum, 1);
161     if (ret != HDF_SUCCESS) {
162         HDF_LOGE("AdcIioReadDrs: read channelNum fail, ret: %d!", ret);
163         return ret;
164     }
165     if (adcDevice->channelNum > ADC_MAX_CHANNEL_NUM) {
166         HDF_LOGE("AdcIioReadDrs: channelNum is illegal!");
167         return HDF_FAILURE;
168     }
169     for (i = 0; i < adcDevice->channelNum; i++) {
170         if (sprintf_s(channelName, ADC_CHANNEL_NAME_LEN - 1, "driver_channel%d_name", i) < 0) {
171             return HDF_FAILURE;
172         }
173         ret = drsOps->GetString(node, channelName, &drName, NULL);
174         if (ret != HDF_SUCCESS) {
175             HDF_LOGE("AdcIioReadDrs: read driver_name fail, ret: %d!", ret);
176             return ret;
177         }
178         adcDevice->driverPathname[i] = drName;
179         adcDevice->fp[i] = NULL;
180         drName = NULL;
181     }
182 
183     ret = drsOps->GetUint32(node, "scanMode", &adcDevice->scanMode, 0);
184     if (ret != HDF_SUCCESS) {
185         HDF_LOGE("AdcIioReadDrs: read scanMode fail, ret: %d!", ret);
186         return ret;
187     }
188 
189     ret = drsOps->GetUint32(node, "rate", &adcDevice->rate, 0);
190     if (ret != HDF_SUCCESS) {
191         HDF_LOGE("AdcIioReadDrs: read rate fail, ret: %d!", ret);
192         return ret;
193     }
194 
195     return HDF_SUCCESS;
196 }
197 
AdcIioParseAndDeviceAdd(struct HdfDeviceObject * device,struct DeviceResourceNode * node)198 static int32_t AdcIioParseAndDeviceAdd(struct HdfDeviceObject *device, struct DeviceResourceNode *node)
199 {
200     int32_t ret;
201     struct AdcIioDevice *adcDevice = NULL;
202 
203     (void)device;
204     adcDevice = (struct AdcIioDevice *)OsalMemCalloc(sizeof(*adcDevice));
205     if (adcDevice == NULL) {
206         HDF_LOGE("AdcIioParseAndDeviceAdd: alloc adcDevice fail!");
207         return HDF_ERR_MALLOC_FAIL;
208     }
209     ret = AdcIioReadDrs(adcDevice, node);
210     if (ret != HDF_SUCCESS) {
211         HDF_LOGE("AdcIioParseAndDeviceAdd: read drs fail, ret: %d!", ret);
212         OsalMemFree(adcDevice);
213         return ret;
214     }
215     adcDevice->device.priv = (void *)node;
216     adcDevice->device.devNum = adcDevice->deviceNum;
217     adcDevice->device.ops = &g_method;
218 
219     ret = AdcDeviceAdd(&adcDevice->device);
220     if (ret != HDF_SUCCESS) {
221         HDF_LOGE("AdcIioParseAndDeviceAdd: add adc device:%u fail!", adcDevice->deviceNum);
222         OsalMemFree(adcDevice);
223         return ret;
224     }
225     return HDF_SUCCESS;
226 }
227 
LinuxAdcInit(struct HdfDeviceObject * device)228 static int32_t LinuxAdcInit(struct HdfDeviceObject *device)
229 {
230     int32_t ret = HDF_SUCCESS;
231     struct DeviceResourceNode *childNode = NULL;
232 
233     if (device == NULL || device->property == NULL) {
234         HDF_LOGE("LinuxAdcInit: device or property is null");
235         return HDF_ERR_INVALID_OBJECT;
236     }
237 
238     DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
239         ret = AdcIioParseAndDeviceAdd(device, childNode);
240         if (ret != HDF_SUCCESS) {
241             return ret;
242         }
243     }
244     HDF_LOGI("LinuxAdcInit: adc iio init success!");
245 
246     return HDF_SUCCESS;
247 }
248 
AdcIioRemoveByNode(const struct DeviceResourceNode * node)249 static void AdcIioRemoveByNode(const struct DeviceResourceNode *node)
250 {
251     int32_t ret;
252     int32_t deviceNum;
253     struct AdcDevice *device = NULL;
254     struct DeviceResourceIface *drsOps = NULL;
255 
256     drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
257     if (drsOps == NULL || drsOps->GetUint32 == NULL) {
258         HDF_LOGE("AdcIioRemoveByNode: invalid drs ops!");
259         return;
260     }
261 
262     ret = drsOps->GetUint32(node, "deviceNum", (uint32_t *)&deviceNum, 0);
263     if (ret != HDF_SUCCESS) {
264         HDF_LOGE("AdcIioRemoveByNode: read deviceNum fail, ret: %d!", ret);
265         return;
266     }
267 
268     device = AdcDeviceGet(deviceNum);
269     if (device != NULL && device->priv == node) {
270         ret = AdcIioStop(device);
271         if (ret != HDF_SUCCESS) {
272             HDF_LOGE("AdcIioRemoveByNode: close fail, ret: %d!", ret);
273         }
274         AdcDevicePut(device);
275         AdcDeviceRemove(device);
276         OsalMemFree(device);
277     }
278 }
279 
LinuxAdcRelease(struct HdfDeviceObject * device)280 static void LinuxAdcRelease(struct HdfDeviceObject *device)
281 {
282     const struct DeviceResourceNode *childNode = NULL;
283     if (device == NULL || device->property == NULL) {
284         HDF_LOGE("LinuxAdcRelease: device or property is null!");
285         return;
286     }
287     DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
288         AdcIioRemoveByNode(childNode);
289     }
290 }
291 
292 struct HdfDriverEntry g_adcLinuxDriverEntry = {
293     .moduleVersion = 1,
294     .Bind = NULL,
295     .Init = LinuxAdcInit,
296     .Release = LinuxAdcRelease,
297     .moduleName = "linux_adc_adapter",
298 };
299 HDF_INIT(g_adcLinuxDriverEntry);
300