• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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