mirror of
https://github.com/openharmony/drivers_framework.git
synced 2026-08-26 18:17:07 -04:00
feat:adc adapts to linux iio framework
Signed-off-by: zhangyalei <zhangyalei7@huawei.com>
This commit is contained in:
@@ -75,12 +75,8 @@ struct AdcTester *AdcTesterGet(void)
|
||||
{
|
||||
int32_t ret;
|
||||
static struct AdcTester tester;
|
||||
static bool hasInit = false;
|
||||
|
||||
HDF_LOGE("%s: enter", __func__);
|
||||
if (hasInit) {
|
||||
return &tester;
|
||||
}
|
||||
ret = AdcTestGetConfig(&tester.config);
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: read config failed:%d", __func__, ret);
|
||||
@@ -91,11 +87,20 @@ struct AdcTester *AdcTesterGet(void)
|
||||
HDF_LOGE("%s: open adc device:%u failed", __func__, tester.config.devNum);
|
||||
return NULL;
|
||||
}
|
||||
hasInit = true;
|
||||
HDF_LOGI("%s: done", __func__);
|
||||
return &tester;
|
||||
}
|
||||
|
||||
static void AdcTesterPut(struct AdcTester *tester)
|
||||
{
|
||||
if (tester == NULL) {
|
||||
HDF_LOGE("%s: tester is NULL", __func__);
|
||||
return;
|
||||
}
|
||||
AdcClose(tester->handle);
|
||||
tester->handle = NULL;
|
||||
}
|
||||
|
||||
int32_t AdcTestRead(void)
|
||||
{
|
||||
struct AdcTester *tester = NULL;
|
||||
@@ -113,11 +118,13 @@ int32_t AdcTestRead(void)
|
||||
value[i] = 0;
|
||||
ret = AdcRead(tester->handle, tester->config.channel, &value[i]);
|
||||
if (ret != HDF_SUCCESS || value[i] >= (1U << tester->config.dataWidth)) {
|
||||
AdcTesterPut(tester);
|
||||
HDF_LOGE("%s: read value failed, ret:%d", __func__, ret);
|
||||
return HDF_ERR_IO;
|
||||
}
|
||||
}
|
||||
|
||||
AdcTesterPut(tester);
|
||||
HDF_LOGI("%s: done", __func__);
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
@@ -142,11 +149,13 @@ static int AdcTestThreadFunc(void *param)
|
||||
if (ret != HDF_SUCCESS) {
|
||||
HDF_LOGE("%s: AdcRead failed, ret:%d", __func__, ret);
|
||||
*((int32_t *)param) = 1;
|
||||
AdcTesterPut(tester);
|
||||
return HDF_ERR_IO;
|
||||
}
|
||||
}
|
||||
|
||||
*((int32_t *)param) = 1;
|
||||
AdcTesterPut(tester);
|
||||
HDF_LOGI("%s: done", __func__);
|
||||
return val;
|
||||
}
|
||||
@@ -217,6 +226,7 @@ int32_t AdcTestReliability(void)
|
||||
(void)AdcRead(tester->handle, tester->config.maxChannel + 1, &val);
|
||||
// invalid val pointer
|
||||
(void)AdcRead(tester->handle, tester->config.channel, NULL);
|
||||
AdcTesterPut(tester);
|
||||
HDF_LOGI("%s: done", __func__);
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
@@ -247,7 +257,10 @@ static int32_t AdcIfPerformanceTest(void)
|
||||
useTime = endMs - startMs;
|
||||
HDF_LOGI("----->interface performance test:[start:%lld(ms) - end:%lld(ms) = %lld (ms)] < 1ms[%d]\r\n",
|
||||
startMs, endMs, useTime, useTime < 1 ? true : false);
|
||||
AdcTesterPut(tester);
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
AdcTesterPut(tester);
|
||||
return HDF_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Huawei Device Co., Ltd.
|
||||
*
|
||||
* HDF is dual licensed: you can use it either under the terms of
|
||||
* the GPL, or the BSD license, at your option.
|
||||
* See the LICENSE file in the root of this repository for complete details.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "hdf_log.h"
|
||||
#include "hdf_base.h"
|
||||
|
||||
#define ADC_SCALE 32680000
|
||||
#define ADC_SCALE_DATA 100000
|
||||
#define ADC_VIRTUAL_RAW_DATA 119
|
||||
#define REAL_BITS 16
|
||||
#define STORAGE_BITS 16
|
||||
#define SHIFT_BITS 0
|
||||
#define SCAN_MASKS 0xF
|
||||
#define BUS_NUM 2
|
||||
|
||||
enum AdcScanIndex {
|
||||
ADC_SCAN_VOLTAGE_1,
|
||||
ADC_SCAN_VOLTAGE_2,
|
||||
};
|
||||
|
||||
struct VirtualAdcDev {
|
||||
char *name;
|
||||
int BusNum;
|
||||
struct mutex lock;
|
||||
};
|
||||
|
||||
static int AdcReadChannelData(struct iio_dev *indioDev, struct iio_chan_spec const *chan, int *val)
|
||||
{
|
||||
if (val == NULL) {
|
||||
HDF_LOGE("%s: val is NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
(void)indioDev;
|
||||
(void)chan;
|
||||
*val = ADC_VIRTUAL_RAW_DATA;
|
||||
return IIO_VAL_INT;
|
||||
}
|
||||
|
||||
/*
|
||||
* val : The value written by the application, val is the integer part if it is a fractional value.
|
||||
* val2 : The value written by the application, if it is a fractional value, val2 is the fractional part.
|
||||
*/
|
||||
static int AdcReadRaw(struct iio_dev *indioDev, struct iio_chan_spec const *chan, int *val, int *val2, long mask)
|
||||
{
|
||||
struct VirtualAdcDev *dev = NULL;
|
||||
int ret;
|
||||
|
||||
if (indioDev == NULL || chan == NULL || val == NULL || val2 == NULL) {
|
||||
HDF_LOGE("%s: Illegal parameter", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (ADC_SCALE_DATA == 0) {
|
||||
HDF_LOGE("%s: ADC_SCALE_DATA is Illegal", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev = iio_priv(indioDev);
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
iio_device_claim_direct_mode(indioDev);
|
||||
mutex_lock(&dev->lock);
|
||||
ret = AdcReadChannelData(indioDev, chan, val);
|
||||
mutex_unlock(&dev->lock);
|
||||
iio_device_release_direct_mode(indioDev);
|
||||
break;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
*val = ADC_SCALE / ADC_SCALE_DATA;
|
||||
*val2 = ADC_SCALE % ADC_SCALE_DATA;
|
||||
ret = IIO_VAL_INT_PLUS_MICRO;
|
||||
break;
|
||||
default:
|
||||
HDF_LOGE("%s: mask is Illegal", __func__);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct iio_chan_spec AdcChannels[] = {
|
||||
{
|
||||
.type = IIO_VOLTAGE,
|
||||
.differential = 1,
|
||||
.indexed = 1,
|
||||
.channel = ADC_SCAN_VOLTAGE_1,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE),
|
||||
.scan_index = ADC_SCAN_VOLTAGE_1,
|
||||
.scan_type = {
|
||||
.sign = 's',
|
||||
.realbits = REAL_BITS,
|
||||
.storagebits = STORAGE_BITS,
|
||||
.shift = SHIFT_BITS,
|
||||
.endianness = IIO_BE,
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = IIO_VOLTAGE,
|
||||
.differential = 1,
|
||||
.indexed = 1,
|
||||
.channel = ADC_SCAN_VOLTAGE_2,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE),
|
||||
.scan_index = ADC_SCAN_VOLTAGE_2,
|
||||
.scan_type = {
|
||||
.sign = 's',
|
||||
.realbits = REAL_BITS,
|
||||
.storagebits = STORAGE_BITS,
|
||||
.shift = SHIFT_BITS,
|
||||
.endianness = IIO_BE,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct iio_info AdcIioInfo = {
|
||||
.read_raw = AdcReadRaw,
|
||||
};
|
||||
|
||||
static void VirtualAdcDevRelease(struct device *dev)
|
||||
{
|
||||
(void)dev;
|
||||
}
|
||||
|
||||
static struct platform_device g_virtualAdcPlatformDevice = {
|
||||
.name = "virtual_adc_dev",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.release = VirtualAdcDevRelease,
|
||||
}
|
||||
};
|
||||
|
||||
static int VirtualAdcPlatformProbe(struct platform_device *pdev)
|
||||
{
|
||||
struct VirtualAdcDev *adcInfo = NULL;
|
||||
struct iio_dev *indioDev = NULL;
|
||||
int ret;
|
||||
|
||||
indioDev = devm_iio_device_alloc(&pdev->dev, sizeof(*adcInfo));
|
||||
if (!indioDev) {
|
||||
HDF_LOGE("%s: malloc iio_dev fail", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
adcInfo = iio_priv(indioDev);
|
||||
adcInfo->name = "virtual-adc-3516";
|
||||
adcInfo->BusNum = BUS_NUM;
|
||||
|
||||
indioDev->name = KBUILD_MODNAME;
|
||||
indioDev->channels = AdcChannels;
|
||||
indioDev->num_channels = ARRAY_SIZE(AdcChannels);
|
||||
indioDev->available_scan_masks = SCAN_MASKS;
|
||||
indioDev->info = &AdcIioInfo;
|
||||
indioDev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
platform_set_drvdata(pdev, indioDev);
|
||||
|
||||
ret = iio_device_register(indioDev);
|
||||
if (ret < 0) {
|
||||
HDF_LOGE("%s: iio device register fail", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static int VirtualAdcPlatformRemove(struct platform_device *pdev)
|
||||
{
|
||||
struct iio_dev *indioDev = NULL;
|
||||
|
||||
indioDev = platform_get_drvdata(pdev);
|
||||
if (indioDev == NULL) {
|
||||
HDF_LOGE("%s: iio device is NULL", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
iio_device_unregister(indioDev);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return HDF_SUCCESS;
|
||||
}
|
||||
|
||||
static struct platform_driver g_virtualAdcPlatformDriver = {
|
||||
.driver = {
|
||||
.name = "virtual_adc_dev",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = VirtualAdcPlatformProbe,
|
||||
.remove = VirtualAdcPlatformRemove,
|
||||
};
|
||||
|
||||
static int __init VirtualAdcInit(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = platform_device_register(&g_virtualAdcPlatformDevice);
|
||||
if (ret == 0) {
|
||||
ret = platform_driver_register(&g_virtualAdcPlatformDriver);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit VirtualAdcExit(void)
|
||||
{
|
||||
platform_device_unregister(&g_virtualAdcPlatformDevice);
|
||||
platform_driver_unregister(&g_virtualAdcPlatformDriver);
|
||||
}
|
||||
module_init(VirtualAdcInit);
|
||||
module_exit(VirtualAdcExit);
|
||||
Reference in New Issue
Block a user