⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adc.c

📁 本文是基于s3c2410自己内部的ADC驱动
💻 C
字号:
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/miscdevice.h> 
#include <linux/sched.h> 
#include <linux/delay.h> 
#include <linux/poll.h> 
#include <linux/spinlock.h> 
#include <linux/delay.h> 
#include <linux/wait.h>


#include <linux/device.h> 
#include <linux/devfs_fs_kernel.h> 
#include <linux/types.h> 
#include <linux/cdev.h> 
#include <linux/errno.h> 
#include <asm/uaccess.h> 
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/arch/regs-mem.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch-s3c2410/regs-adc.h>
#include <asm/arch-s3c2410/regs-clock.h>
#include <asm-arm/arch-s3c2410/map.h>

#include "adc.h"


#define DEVICE_NAME			"adc" 

static void __iomem *base_addr;

static int adc_major = 0;


static ssize_t adc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
	int data;
	unsigned long tmp;
	//start ADC
	tmp = readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START;
	writel( tmp, base_addr+S3C2410_ADCCON);
	//state
	do{
		tmp = readl(base_addr+S3C2410_ADCCON);
	}while(!(((unsigned int)tmp)&0x8000));
	//read data
	data = readl(base_addr+S3C2410_ADCDAT0) & 0x3ff;
	
	if(copy_to_user(buf, &data, sizeof(int)))
			return -EFAULT;
	return (sizeof(int));
}

static ssize_t adc_write(struct file * file, const char __user * buf, size_t count, loff_t * off)
{
	unsigned long tmp;
	struct ADC_DEV adcdev;
	
	copy_from_user(&adcdev,(struct ADC_DEV *)buf,sizeof(struct ADC_DEV));
	
	//S3C2410_CLKCON
	writel((readl(S3C2410_CLKCON) | S3C2410_CLKCON_ADC),S3C2410_CLKCON);
	//S3C2410_ADCTSC
	tmp = readl(base_addr+S3C2410_ADCTSC);
	tmp &= (~S3C2410_ADCTSC_AUTO_PST) | S3C2410_ADCTSC_XY_PST(S3C2410_NOP_MODE);
	writel(tmp , base_addr+S3C2410_ADCTSC);
	//S3C2410_ADCCON
	tmp = readl(base_addr+S3C2410_ADCCON);
	tmp = S3C2410_ADCCON_PRSCEN|S3C2410_ADCCON_PRSCVL(adcdev.prescale)|S3C2410_ADCCON_SELMUX(adcdev.channel);
	writel( tmp, base_addr+S3C2410_ADCCON);
	return 0;
}

static int adc_open(struct inode * inode, struct file * filp)
{
	return 0;
}

static int adc_release(struct inode * inode, struct file * filp)
{
	return 0;
}

static struct file_operations adc_fops = {
	 
	.owner = THIS_MODULE,
	.write = adc_write, 
	.read = adc_read,
	.open  = adc_open,	
	.release=adc_release,
}; 

static int __init adc_init(void)
{
	int ret;
	
	ret = register_chrdev(0,DEVICE_NAME,&adc_fops);
  	if(ret < 0) 
	{
		printk("adc: can't get major number\n");
       	return ret;
	}
	
	adc_major = ret;

#ifdef CONFIG_DEVFS_FS   
    ret = devfs_mk_cdev(MKDEV(adc_major,0),  S_IFCHR | S_IRUGO | S_IWUSR,DEVICE_NAME);
	if(ret)
	{
		unregister_chrdev(adc_major,DEVICE_NAME); 
		printk("adc: can't make char device fo devfs\n");
		return ret;
	}
#endif
	
	base_addr=ioremap(S3C2410_PA_ADC,4);
    if (base_addr == NULL) 
    {
		printk(KERN_ERR "Failed to remap register block\n");
    	return -ENOMEM;
    }
    
    printk("s3c2410_adc driver initial\n");
    
	return 0;
}

static void __exit adc_exit(void)
{
#ifdef CONFIG_DEVFS_FS
	devfs_remove(DEVICE_NAME);
#endif  
	unregister_chrdev(adc_major,DEVICE_NAME);
	 
	iounmap(base_addr);
	
    printk("s3c2410_adc driver removed\n"); 
}

module_init(adc_init);
module_exit(adc_exit);

MODULE_ALIAS("adc"); 
MODULE_DESCRIPTION("ADC IO Driver For EM104-MINI2410");
MODULE_AUTHOR("LIANXJ");
MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -