• 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 #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