4412 ADC驱动示例

9 篇文章 0 订阅
#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");





  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值