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