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