#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/ioport.h>
#include <linux/io.h>
#include <linux/wait.h>
#include <linux/irqreturn.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/uaccess.h>
#define DEV_NAME "adc"
#define ADCCON 0
#define ADCDAT 0XC
#define ADCINT 0X18
#define ADCMUX 0X1C
/**
* myadc {
1 compatible = "xadc";
2 reg = <0x10010118 0x1>, <0x126C0000 0x20>;
3 interrupt-parent = <&combiner>;
4 // ADC --> SPI 10, child group 3
5 interrupts = <10 3>;
6 };
* */
int flag = 0;
int major = 0;
void __iomem* adc_base;
struct resource *res1,*res2;
wait_queue_head_t q;
irqreturn_t adc_irq_handle(int irq, void *data)
{
writel(1,(adc_base + ADCINT));
wake_up_interruptible(&q);
flag = 1;
return IRQ_HANDLED;//表征中断处理完成
}
ssize_t adc_read(struct file *file, char __user *user, size_t size, loff_t *loff)
{
int buf;
/*ADC寄存器配置*/
/*配置通道 +设置分频及分辨率 */
writel( 3, (adc_base + ADCMUX));
writel(1<<16|1<<14|0XFF<<6|1<<0,(adc_base + ADCCON));
wait_event_interruptible(q, flag);
buf = readl((adc_base + ADCDAT));
if(copy_to_user(user,&buf,sizeof(buf))){
printk("copy_to_user\n");
}
flag = 0;
//printk("%s,%d\n",__func__,__LINE__);
return size;
}
ssize_t adc_write(struct file *file, const char __user *user, size_t size, loff_t * loff)
{
printk("%s,%d\n",__func__,__LINE__);
return 0;
}
int adc_open(struct inode *inode, struct file *file)
{
int ret;
adc_base = ioremap(res1->start ,((res1->end) - (res1->start)) + 1);//reg_base
/*因为ADC采用中断进行数据唤醒*/
ret = request_irq(res2->start, adc_irq_handle, IRQF_DISABLED,DEV_NAME,NULL);
if(ret){
printk("request_irq fail\n");
return EINVAL;
}
printk("%s,%d\n",__func__,__LINE__);
return 0;
}
int adc_release(struct inode *inode, struct file *file)
{
iounmap(adc_base);
printk("%s,%d\n",__func__,__LINE__);
return 0;
}
struct file_operations f_ops = {
.owner = THIS_MODULE,
.open = adc_open,
.release = adc_release,
.read = adc_read,
.write = adc_write,
};
int pdrv_probe(struct platform_device *pdev)
{
int ret;
/*获取硬件资源*/
res1 = platform_get_resource(pdev,IORESOURCE_MEM,1);//reg 由于设备树的关系 这里从第一个寄存器开解析,跳过第0个寄存器
printk("%s,%d: res1 = %p\n",__func__,__LINE__, res1->start);
res2 = platform_get_resource(pdev,IORESOURCE_IRQ,0);//IRQ
printk("%s,%d: res2 = %d\n",__func__,__LINE__, res2->start);
if((res1 == NULL)||(res2 == NULL)){
printk("platform_get_resource FAIL\n");
return -ENOMEM;
}
init_waitqueue_head(&q);
/*字符设备的编写*/
ret = register_chrdev(major, DEV_NAME , &f_ops);
printk("%s,%d, major = %d\n",__func__,__LINE__, ret);
if(ret < 0){
printk("register_chrdev FAIL\n");
return -EINVAL;
}
printk("%s,%d\n",__func__,__LINE__);
return 0;
}
int pdrv_remove(struct platform_device *pdev)
{
unregister_chrdev(major,DEV_NAME);
printk("%s,%d\n",__func__,__LINE__);
return 0;
}
const struct platform_device_id pdev_id_table[] = {
{.name = "pdev"},
{},
};
const struct of_device_id of_pdrv_table[] = {
[0] = {.compatible = "xadc"},
[1] = {}
};
MODULE_DEVICE_TABLE(of,of_pdrv_table);
/*2.platform_driver结构体填充*/
struct platform_driver pdrv = {
.probe = pdrv_probe,
.remove = pdrv_remove,
.driver = {
.name = "xadc",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(of_pdrv_table),
},
.id_table = pdev_id_table,
};
/*编写流程:*/
/*1.模块三要素*/
static int __init pdrv_init(void)
{
/*4.注册/注销*/
platform_driver_register(&pdrv);
printk("%s,%d\n",__func__,__LINE__);
return 0;
}
static void __exit pdrv_exit(void)
{
platform_driver_unregister(&pdrv);
printk("%s,%d\n",__func__,__LINE__);
}
module_init(pdrv_init);
module_exit(pdrv_exit);
MODULE_LICENSE("GPL");
4412 ADC驱动示例
最新推荐文章于 2023-01-11 17:09:49 发布