1 /*
2 * Copyright (c) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
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 #include "adc_hi35xx.h"
17 #include "adc_core.h"
18 #include "asm/platform.h"
19 #include "device_resource_if.h"
20 #include "hdf_device_desc.h"
21 #include "hdf_log.h"
22 #include "los_hwi.h"
23 #include "osal_io.h"
24 #include "osal_mem.h"
25 #include "osal_time.h"
26
27 #define HDF_LOG_TAG adc_hi35xx
28 #define HI35XX_ADC_READ_DELAY 10
29
30 struct Hi35xxAdcDevice {
31 struct AdcDevice device;
32 volatile unsigned char *regBase;
33 volatile unsigned char *pinCtrlBase;
34 uint32_t regBasePhy;
35 uint32_t regSize;
36 uint32_t deviceNum;
37 uint32_t dataWidth;
38 uint32_t validChannel;
39 uint32_t scanMode;
40 uint32_t delta;
41 uint32_t deglitch;
42 uint32_t glitchSample;
43 uint32_t rate;
44 };
45
Hi35xxAdcSetIrq(const struct Hi35xxAdcDevice * hi35xx)46 static inline void Hi35xxAdcSetIrq(const struct Hi35xxAdcDevice *hi35xx)
47 {
48 OSAL_WRITEL(0, hi35xx->regBase + HI35XX_ADC_INTR_EN);
49 }
50
Hi35xxAdcSetAccuracy(const struct Hi35xxAdcDevice * hi35xx)51 static void Hi35xxAdcSetAccuracy(const struct Hi35xxAdcDevice *hi35xx)
52 {
53 uint32_t dataWidth;
54 uint32_t val;
55
56 if (hi35xx->dataWidth != 0 && hi35xx->dataWidth <= MAX_DATA_WIDTH) {
57 dataWidth = hi35xx->dataWidth;
58 } else {
59 dataWidth = DEFAULT_DATA_WIDTH;
60 }
61
62 val = ((DATA_WIDTH_MASK << (MAX_DATA_WIDTH - dataWidth)) & DATA_WIDTH_MASK);
63 OSAL_WRITEL(val, hi35xx->regBase + HI35XX_ADC_ACCURACY);
64 }
65
Hi35xxAdcSetGlitchSample(const struct Hi35xxAdcDevice * hi35xx)66 static void Hi35xxAdcSetGlitchSample(const struct Hi35xxAdcDevice *hi35xx)
67 {
68 uint32_t val;
69
70 if (hi35xx->scanMode == CYCLE_MODE) {
71 val = (hi35xx->glitchSample == CYCLE_MODE) ? DEFAULT_GLITCHSAMPLE : hi35xx->glitchSample;
72 OSAL_WRITEL(val, hi35xx->regBase + HI35XX_ADC_START);
73 val = OSAL_READL(hi35xx->regBase + HI35XX_ADC_START);
74 HDF_LOGD("%s: glichSample reg val:%x", __func__, val);
75 }
76 }
77
Hi35xxAdcSetTimeScan(const struct Hi35xxAdcDevice * hi35xx)78 static void Hi35xxAdcSetTimeScan(const struct Hi35xxAdcDevice *hi35xx)
79 {
80 uint32_t timeScan;
81 uint32_t rate;
82
83 rate = hi35xx->rate;
84 if (hi35xx->scanMode == CYCLE_MODE) {
85 timeScan = (TIME_SCAN_CALCULATOR / rate);
86 if (timeScan < TIME_SCAN_MINIMUM) {
87 timeScan = TIME_SCAN_MINIMUM;
88 }
89 OSAL_WRITEL(timeScan, hi35xx->regBase + HI35XX_ADC_START);
90 timeScan = OSAL_READL(hi35xx->regBase + HI35XX_ADC_START);
91 HDF_LOGD("%s: tiemScan reg val:%x", __func__, timeScan);
92 }
93 }
94
Hi35xxAdcConfig(const struct Hi35xxAdcDevice * hi35xx)95 static void Hi35xxAdcConfig(const struct Hi35xxAdcDevice *hi35xx)
96 {
97 uint32_t validChannel;
98 uint32_t scanMode;
99 uint32_t delta;
100 uint32_t deglitch;
101 uint32_t val;
102
103 validChannel = hi35xx->validChannel;
104 scanMode = hi35xx->scanMode;
105 delta = hi35xx->delta;
106 deglitch = hi35xx->deglitch;
107
108 if (scanMode == CYCLE_MODE) {
109 val = (delta & DELTA_MASK) << DELTA_OFFSET;
110 val |= ((~deglitch) & 1) << DEGLITCH_OFFSET;
111 }
112 val = ((~scanMode) & 1) << SCAN_MODE_OFFSET;
113 val |= (validChannel & VALID_CHANNEL_MASK) << VALID_CHANNEL_OFFSET;
114 OSAL_WRITEL(val, hi35xx->regBase + HI35XX_ADC_CONFIG);
115 }
116
Hi35xxAdcStartScan(const struct Hi35xxAdcDevice * hi35xx)117 static inline void Hi35xxAdcStartScan(const struct Hi35xxAdcDevice *hi35xx)
118 {
119 OSAL_WRITEL(1, hi35xx->regBase + HI35XX_ADC_START);
120 }
121
Hi35xxAdcReset(const struct Hi35xxAdcDevice * hi35xx)122 static inline void Hi35xxAdcReset(const struct Hi35xxAdcDevice *hi35xx)
123 {
124 OSAL_WRITEL(CONFIG_REG_RESET_VALUE, hi35xx->regBase + HI35XX_ADC_CONFIG);
125 }
126
Hi35xxAdcSetPinCtrl(const struct Hi35xxAdcDevice * hi35xx)127 static void Hi35xxAdcSetPinCtrl(const struct Hi35xxAdcDevice *hi35xx)
128 {
129 uint32_t val;
130 uint32_t validChannel;
131
132 validChannel = (hi35xx->validChannel & VALID_CHANNEL_MASK);
133 if ((validChannel & 0x1) == 1) {
134 val = OSAL_READL(hi35xx->pinCtrlBase + HI35XX_ADC_IO_CONFIG_0);
135 val &= ~PINCTRL_MASK;
136 OSAL_WRITEL(val, hi35xx->pinCtrlBase + HI35XX_ADC_IO_CONFIG_0);
137 }
138 validChannel = validChannel >> 1;
139 if ((validChannel & 0x1) == 1) {
140 val = OSAL_READL(hi35xx->pinCtrlBase + HI35XX_ADC_IO_CONFIG_1);
141 val &= ~PINCTRL_MASK;
142 OSAL_WRITEL(val, hi35xx->pinCtrlBase + HI35XX_ADC_IO_CONFIG_1);
143 }
144 }
145
Hi35xxAdcStart(struct AdcDevice * device)146 static inline int32_t Hi35xxAdcStart(struct AdcDevice *device)
147 {
148 struct Hi35xxAdcDevice *hi35xx = NULL;
149
150 if (device == NULL || device->priv == NULL) {
151 HDF_LOGE("%s: device or priv is null", __func__);
152 return HDF_ERR_INVALID_OBJECT;
153 }
154 hi35xx = (struct Hi35xxAdcDevice *)device;
155 if (hi35xx->scanMode == CYCLE_MODE) {
156 Hi35xxAdcStartScan(hi35xx);
157 }
158 return HDF_SUCCESS;
159 }
160
Hi35xxAdcRead(struct AdcDevice * device,uint32_t channel,uint32_t * val)161 static int32_t Hi35xxAdcRead(struct AdcDevice *device, uint32_t channel, uint32_t *val)
162 {
163 uint32_t value;
164 uint32_t dataWidth;
165 struct Hi35xxAdcDevice *hi35xx = NULL;
166
167 if (device == NULL || device->priv == NULL) {
168 HDF_LOGE("%s: device or priv is null", __func__);
169 return HDF_ERR_INVALID_OBJECT;
170 }
171 hi35xx = (struct Hi35xxAdcDevice *)device;
172 Hi35xxAdcStartScan(hi35xx);
173
174 if (hi35xx->scanMode != CYCLE_MODE) {
175 OsalUDelay(HI35XX_ADC_READ_DELAY);
176 }
177
178 switch (channel) {
179 case 0:
180 value = OSAL_READL(hi35xx->regBase + HI35XX_ADC_DATA0);
181 break;
182 case 1:
183 value = OSAL_READL(hi35xx->regBase + HI35XX_ADC_DATA1);
184 break;
185 default:
186 value = 0;
187 HDF_LOGE("%s: invalid channel:%u", __func__, channel);
188 return HDF_ERR_INVALID_PARAM;
189 }
190
191 dataWidth = hi35xx->dataWidth;
192 value = value >> (MAX_DATA_WIDTH - dataWidth);
193 *val = value;
194 return HDF_SUCCESS;
195 }
196
Hi35xxAdcStop(struct AdcDevice * device)197 static inline int32_t Hi35xxAdcStop(struct AdcDevice *device)
198 {
199 struct Hi35xxAdcDevice *hi35xx = NULL;
200
201 if (device == NULL || device->priv == NULL) {
202 HDF_LOGE("%s: device or priv is null", __func__);
203 return HDF_ERR_INVALID_OBJECT;
204 }
205 hi35xx = (struct Hi35xxAdcDevice *)device;
206 if (hi35xx->scanMode == CYCLE_MODE) {
207 OSAL_WRITEL(1, hi35xx->regBase + HI35XX_ADC_STOP);
208 }
209 return HDF_SUCCESS;
210 }
211
212 static const struct AdcMethod g_method = {
213 .read = Hi35xxAdcRead,
214 .stop = Hi35xxAdcStop,
215 .start = Hi35xxAdcStart,
216 };
217
Hi35xxAdcDeviceInit(struct Hi35xxAdcDevice * hi35xx)218 static void Hi35xxAdcDeviceInit(struct Hi35xxAdcDevice *hi35xx)
219 {
220 Hi35xxAdcReset(hi35xx);
221 Hi35xxAdcConfig(hi35xx);
222 Hi35xxAdcSetAccuracy(hi35xx);
223 Hi35xxAdcSetIrq(hi35xx);
224 Hi35xxAdcSetGlitchSample(hi35xx);
225 Hi35xxAdcSetTimeScan(hi35xx);
226 Hi35xxAdcSetPinCtrl(hi35xx);
227 HDF_LOGI("%s: device:%u init done", __func__, hi35xx->deviceNum);
228 }
229
Hi35xxAdcReadDrs(struct Hi35xxAdcDevice * hi35xx,const struct DeviceResourceNode * node)230 static int32_t Hi35xxAdcReadDrs(struct Hi35xxAdcDevice *hi35xx, const struct DeviceResourceNode *node)
231 {
232 int32_t ret;
233 struct DeviceResourceIface *drsOps = NULL;
234
235 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
236 if (drsOps == NULL || drsOps->GetUint32 == NULL) {
237 HDF_LOGE("%s: invalid drs ops", __func__);
238 return HDF_ERR_NOT_SUPPORT;
239 }
240
241 ret = drsOps->GetUint32(node, "regBasePhy", &hi35xx->regBasePhy, 0);
242 if (ret != HDF_SUCCESS) {
243 HDF_LOGE("%s: read regBasePhy failed", __func__);
244 return ret;
245 }
246
247 ret = drsOps->GetUint32(node, "regSize", &hi35xx->regSize, 0);
248 if (ret != HDF_SUCCESS) {
249 HDF_LOGE("%s: read regSize failed", __func__);
250 return ret;
251 }
252
253 ret = drsOps->GetUint32(node, "deviceNum", &hi35xx->deviceNum, 0);
254 if (ret != HDF_SUCCESS) {
255 HDF_LOGE("%s: read deviceNum failed", __func__);
256 return ret;
257 }
258
259 ret = drsOps->GetUint32(node, "dataWidth", &hi35xx->dataWidth, 0);
260 if (ret != HDF_SUCCESS) {
261 HDF_LOGE("%s: read dataWidth failed", __func__);
262 return ret;
263 }
264
265 ret = drsOps->GetUint32(node, "validChannel", &hi35xx->validChannel, 0);
266 if (ret != HDF_SUCCESS) {
267 HDF_LOGE("%s: read validChannel failed", __func__);
268 return ret;
269 }
270
271 ret = drsOps->GetUint32(node, "scanMode", &hi35xx->scanMode, 0);
272 if (ret != HDF_SUCCESS) {
273 HDF_LOGE("%s: read scanMode failed", __func__);
274 return ret;
275 }
276
277 ret = drsOps->GetUint32(node, "delta", &hi35xx->delta, 0);
278 if (ret != HDF_SUCCESS) {
279 HDF_LOGE("%s: read delta failed", __func__);
280 return ret;
281 }
282
283 ret = drsOps->GetUint32(node, "deglitch", &hi35xx->deglitch, 0);
284 if (ret != HDF_SUCCESS) {
285 HDF_LOGE("%s: read deglitch failed", __func__);
286 return ret;
287 }
288
289 ret = drsOps->GetUint32(node, "glitchSample", &hi35xx->glitchSample, 0);
290 if (ret != HDF_SUCCESS) {
291 HDF_LOGE("%s: read glitchSample failed", __func__);
292 return ret;
293 }
294
295 ret = drsOps->GetUint32(node, "rate", &hi35xx->rate, 0);
296 if (ret != HDF_SUCCESS) {
297 HDF_LOGE("%s: read rate failed", __func__);
298 return ret;
299 }
300 return HDF_SUCCESS;
301 }
302
Hi35xxAdcParseInit(struct HdfDeviceObject * device,struct DeviceResourceNode * node)303 static int32_t Hi35xxAdcParseInit(struct HdfDeviceObject *device, struct DeviceResourceNode *node)
304 {
305 int32_t ret;
306 struct Hi35xxAdcDevice *hi35xx = NULL;
307
308 (void)device;
309 hi35xx = (struct Hi35xxAdcDevice *)OsalMemCalloc(sizeof(*hi35xx));
310 if (hi35xx == NULL) {
311 HDF_LOGE("%s: alloc hi35xx failed", __func__);
312 return HDF_ERR_MALLOC_FAIL;
313 }
314
315 ret = Hi35xxAdcReadDrs(hi35xx, node);
316 if (ret != HDF_SUCCESS) {
317 HDF_LOGE("%s: read drs failed:%d", __func__, ret);
318 goto __ERR__;
319 }
320
321 hi35xx->regBase = OsalIoRemap(hi35xx->regBasePhy, hi35xx->regSize);
322 if (hi35xx->regBase == NULL) {
323 HDF_LOGE("%s: remap regbase failed", __func__);
324 ret = HDF_ERR_IO;
325 goto __ERR__;
326 }
327
328 hi35xx->pinCtrlBase = OsalIoRemap(HI35XX_ADC_IO_CONFIG_BASE, HI35XX_ADC_IO_CONFIG_SIZE);
329 if (hi35xx->pinCtrlBase == NULL) {
330 HDF_LOGE("%s: remap pinctrl base failed", __func__);
331 ret = HDF_ERR_IO;
332 goto __ERR__;
333 }
334
335 Hi35xxAdcDeviceInit(hi35xx);
336 hi35xx->device.priv = (void *)node;
337 hi35xx->device.devNum = hi35xx->deviceNum;
338 hi35xx->device.ops = &g_method;
339 ret = AdcDeviceAdd(&hi35xx->device);
340 if (ret != HDF_SUCCESS) {
341 HDF_LOGE("%s: add adc device:%u failed", __func__, hi35xx->deviceNum);
342 goto __ERR__;
343 }
344 return HDF_SUCCESS;
345
346 __ERR__:
347 if (hi35xx != NULL) {
348 if (hi35xx->regBase != NULL) {
349 OsalIoUnmap((void *)hi35xx->regBase);
350 hi35xx->regBase = NULL;
351 }
352 AdcDeviceRemove(&hi35xx->device);
353 OsalMemFree(hi35xx);
354 }
355 return ret;
356 }
357
Hi35xxAdcInit(struct HdfDeviceObject * device)358 static int32_t Hi35xxAdcInit(struct HdfDeviceObject *device)
359 {
360 int32_t ret;
361 struct DeviceResourceNode *childNode = NULL;
362
363 if (device == NULL || device->property == NULL) {
364 HDF_LOGE("%s: device or property is null", __func__);
365 return HDF_ERR_INVALID_OBJECT;
366 }
367
368 ret = HDF_SUCCESS;
369 DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
370 ret = Hi35xxAdcParseInit(device, childNode);
371 if (ret != HDF_SUCCESS) {
372 break;
373 }
374 }
375 HDF_LOGI("%s: adc init success.", __func__);
376 return ret;
377 }
378
Hi35xxAdcRemoveByNode(const struct DeviceResourceNode * node)379 static void Hi35xxAdcRemoveByNode(const struct DeviceResourceNode *node)
380 {
381 int32_t ret;
382 int32_t deviceNum;
383 struct AdcDevice *device = NULL;
384 struct Hi35xxAdcDevice *hi35xx = NULL;
385 struct DeviceResourceIface *drsOps = NULL;
386
387 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
388 if (drsOps == NULL || drsOps->GetUint32 == NULL) {
389 HDF_LOGE("%s: invalid drs ops", __func__);
390 return;
391 }
392
393 ret = drsOps->GetUint32(node, "deviceNum", (uint32_t *)&deviceNum, 0);
394 if (ret != HDF_SUCCESS) {
395 HDF_LOGE("%s: read deviceNum failed", __func__);
396 return;
397 }
398
399 device = AdcDeviceGet(deviceNum);
400 if (device != NULL && device->priv == node) {
401 AdcDevicePut(device);
402 AdcDeviceRemove(device);
403 hi35xx = (struct Hi35xxAdcDevice *)device;
404 OsalIoUnmap((void *)hi35xx->regBase);
405 OsalMemFree(hi35xx);
406 }
407 return;
408 }
409
Hi35xxAdcRelease(struct HdfDeviceObject * device)410 static void Hi35xxAdcRelease(struct HdfDeviceObject *device)
411 {
412 const struct DeviceResourceNode *childNode = NULL;
413
414 HDF_LOGI("%s: enter", __func__);
415 if (device == NULL || device->property == NULL) {
416 HDF_LOGE("%s: device or property is null", __func__);
417 return;
418 }
419 DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
420 Hi35xxAdcRemoveByNode(childNode);
421 }
422 }
423
424 static struct HdfDriverEntry g_hi35xxAdcDriverEntry = {
425 .moduleVersion = 1,
426 .Init = Hi35xxAdcInit,
427 .Release = Hi35xxAdcRelease,
428 .moduleName = "hi35xx_adc_driver",
429 };
430 HDF_INIT(g_hi35xxAdcDriverEntry);
431