Qcom 平台 pmic adc读取代码实现
Qcom 平台读取pmic上 adc电压值的方法
如下图,可以通过平台提供的节点(参考高通文档将mpp配置为adc功能) cat对应的节点获取结果;
也可以通过自行实现的驱动中调用相关接口并转化结果;
Kernel demo 参考代码:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <asm/uaccess.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/consumer.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/qpnp/qpnp-adc.h>
#include <linux/time.h>static struct workqueue_struct *init_mpp2_adc_wq;
static struct delayed_work init_work;static struct mpp2_adc_data
{char name;int major;struct class *class;struct platform_device *pdev;struct qpnp_vadc_chip *vadc_dev;
}qm215_mpp2_adc;ssize_t mpp2_adc_read (struct file *file, char __user *buf, size_t size, loff_t * loft)
{ int ret;int adc_val = 0;int i = 0;char adc[16];char count = 0;struct qpnp_vadc_result result;if(*loft)return 0;printk("qm215 mpp2_adc read adc\n");ret = qpnp_vadc_read(qm215_mpp2_adc.vadc_dev,P_MUX2_1_1,&result);if(ret < 0){printk("qm215 mpp2_adc qpnp_vadc_read fail\n");return size;}printk("qm215 mpp2_adc read adc end\n");adc_val = (int)result.physical;
// adc_val = adc_val / 1000;printk("qm215 mpp2_adc read adc_val: %d uv\n",adc_val);memset(adc,0,sizeof(adc));count = sprintf(adc,"%d", adc_val);do{adc_val = adc_val / 10;i++;}while(adc_val);ret = copy_to_user(buf, adc, i+1);*loft += (i+1);return i+1;
}static struct file_operations mpp2_adc_ops =
{.owner = THIS_MODULE,.read = mpp2_adc_read,
};
static void mpp2_adc_init_work(struct work_struct *work)
{printk("qm215 mpp2_adc init work\n");qm215_mpp2_adc.vadc_dev = qpnp_get_vadc(&qm215_mpp2_adc.pdev->dev,"test");if(qm215_mpp2_adc.vadc_dev == NULL)printk("qm215 qpnp_get_vadc fail \n ");if( IS_ERR(qm215_mpp2_adc.vadc_dev))printk("qm215 qpnp_get_vadc fail errno is %d\n", (int)PTR_ERR(qm215_mpp2_adc.vadc_dev));
}static int mpp2_adc_platform_probe(struct platform_device *pdev)
{int ret;
// struct device_node *np = pdev->dev.of_node;printk("qm215 mpp2_adc_read probe \n");qm215_mpp2_adc.pdev = pdev;qm215_mpp2_adc.major = register_chrdev(0, "mpp2_adc", &mpp2_adc_ops);qm215_mpp2_adc.class = class_create(THIS_MODULE, "mpp2_adc");device_create(qm215_mpp2_adc.class, NULL, MKDEV(qm215_mpp2_adc.major, 0), NULL, "mpp2_adc");INIT_DELAYED_WORK(&init_work, mpp2_adc_init_work);init_mpp2_adc_wq = create_singlethread_workqueue("init_mpp2_adc_wq");if (!init_mpp2_adc_wq) {ret = -EINVAL;}queue_delayed_work(init_mpp2_adc_wq, &init_work, 10*HZ);return 0;
}static int mpp2_adc_platform_remove(struct platform_device *pdev)
{device_destroy(qm215_mpp2_adc.class, MKDEV(qm215_mpp2_adc.major, 0));class_destroy(qm215_mpp2_adc.class);unregister_chrdev(qm215_mpp2_adc.major, "mpp2_adc");return 0;
}static struct of_device_id mpp2_adc_of_match[] = {{ .compatible = "qm215,mpp2_adc", },{},
};static struct platform_driver mpp2_adc_platform_driver = {.probe = mpp2_adc_platform_probe,.remove = mpp2_adc_platform_remove,.driver = {.owner = THIS_MODULE,.name = "qm215,mpp2_adc",.of_match_table = of_match_ptr(mpp2_adc_of_match),}
};static int __init mpp2_adc_init(void)
{int ret = 0;printk("qm215 mpp2_adc init\n");ret = platform_driver_register(&mpp2_adc_platform_driver);if(ret< 0){printk("qm215 mpp2_adc platform driver register fail\n");return -1;}printk("qm215 mpp2_adc end\n");return 0;
}
static void __exit mpp2_adc_exit(void)
{platform_driver_unregister(&mpp2_adc_platform_driver);
}module_init(mpp2_adc_init);
module_exit(mpp2_adc_exit);MODULE_AUTHOR("xxx");
MODULE_DESCRIPTION("mpp2_adc");
MODULE_LICENSE("GPL");