#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/device.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/ioctl.h>
#include <linux/uaccess.h>
#define IOC_MAGIC 'c'
/* 初始化设备 */
#define IOCINIT _IO(IOC_MAGIC, 0)
/* 读寄存器 */
#define IOCGREG _IOW(IOC_MAGIC, 1, int)
/* 写寄存器 */
#define IOCWREG _IOR(IOC_MAGIC, 2, int)
#define IOC_MAXNR 3
//连续扫描
#define Continuous_Scanning
//#define Single_Scanning
#define MAX_SIZE 0x1000
#define MEM_CLEAR 0x1
#define LSADC_RGG_BASE_ADDR 0x11080000
#define LSADC_REG(x) baseaddr+(x)
#define LSADC_CTRL0 LSADC_REG(0x0000)
#define LSADC_CTRL1 LSADC_REG(0x0004)
#define LSADC_CTRL2 LSADC_REG(0x0008)
#define LSADC_CTRL4 LSADC_REG(0x0010)
#define LSADC_CTRL5 LSADC_REG(0x0014)
#define LSADC_CTRL6 LSADC_REG(0x0018)
#define LSADC_CTRL7 LSADC_REG(0x001c)
#define LSADC_CTRL8 LSADC_REG(0x0020)
#define LSADC_CTRL9 LSADC_REG(0x0024)
#define LSADC_CTRL10 LSADC_REG(0x0028)
#define LSADC_CTRL11 LSADC_REG(0x002C)
#define LSADC_CTRL12 LSADC_REG(0x0030)
#define LSADC_CTRL13 LSADC_REG(0x0034)
#define LSADC_CTRL14 LSADC_REG(0x0038)
static void __iomem *baseaddr; // 寄存器的虚拟地址的基地址
static struct class *cls;
static struct device *dev;
static int lsadc_major;
struct virtdev_dev
{
struct cdev cdev;
unsigned char mem[MAX_SIZE];
};
struct virtdev_dev *devp;
dev_t devno;
struct msg {
int addr;
unsigned int data;
};
static int virtdev_open(struct inode *inode, struct file *filp)
{
*devp->mem = "0x1234567890";
filp->private_data = devp;
return 0;
}
static int virtdev_release(struct inode *inode, struct file *filp)
{
return 0;
}
static long virtdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
long ret;
struct msg my_msg;
//printk(KERN_EMERG"[%s] command numer [%d] exceeded!\n",
// __func__, _IOC_NR(cmd));
switch (cmd) {
/* 初始化设备 */
case IOCINIT:
printk(KERN_EMERG"__init\n");
break;
/* 读寄存器 */
case IOCGREG:
// printk(KERN_EMERG"__read\n");
ret = copy_from_user(&my_msg, \
(struct msg __user *)arg, sizeof(my_msg));
if (ret)
return -EFAULT;
#ifdef Single_Scanning
writel(0x1, LSADC_CTRL7);
#endif // Single_Scanning
my_msg.data = readl(LSADC_CTRL11);//ADC CHN0
ret = copy_to_user((struct msg __user *)arg, \
&my_msg, sizeof(my_msg));
if (ret)
return -EFAULT;
break;
/* 写寄存器 */
case IOCWREG:
//printk(KERN_EMERG"__write\n");
ret = copy_from_user(&my_msg, \
(struct msg __user *)arg, sizeof(my_msg));
printk(KERN_EMERG"msg addr is %x,value is %x\n",my_msg.addr, my_msg.data);
if (ret)
return -EFAULT;
//write_reg(msg->addr, msg->data);
break;
default:
return -ENOTTY;
}
return 0;
}
static ssize_t virtdev_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
unsigned long p = *ppos;
unsigned int count = size;
int ret = 0;
struct virtdev_dev *dev = filp->private_data;
if (p >= MAX_SIZE)
return -EINVAL;
if (count > MAX_SIZE - p)
count = MAX_SIZE - p;
if (copy_to_user(buf, dev->mem + p, count))
ret = -EINVAL;
else
{
*ppos += count;
ret = count;
printk(KERN_INFO "read %u byte(s) from %lu\n", count, p);
}
return ret;
}
static ssize_t virtdev_write(struct file *filp, const char __user *buf, size_t size,
loff_t *ppos)
{
unsigned long p = *ppos;
unsigned int count = size;
int ret = 0;
struct virtdev_dev *dev = filp->private_data;
if (p >= MAX_SIZE)
return -EINVAL;
if (count > MAX_SIZE - p)
count = MAX_SIZE - p;
if (copy_from_user(dev->mem + p, buf, count))
ret = -EINVAL;
else
{
*ppos += count;
ret = count;
printk(KERN_INFO "write %u byte(s) from %lu\n", count, p);
}
return ret;
}
static loff_t virtdev_llseek(struct file *filp, loff_t offset, int orig)
{
loff_t ret = 0;
switch (orig)
{
case 0:
if (offset < 0)
{
ret = -EINVAL;
break;
}
if (offset > MAX_SIZE)
{
ret = -EINVAL;
break;
}
filp->f_pos = offset;
ret = filp->f_pos;
break;
case 1:
if ((filp->f_pos + offset) < 0)
{
ret = -EINVAL;
break;
}
if ((filp->f_pos + offset) > MAX_SIZE)
{
ret = -EINVAL;
break;
}
filp->f_pos += offset;
ret = filp->f_pos;
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
static struct file_operations virtdev_fops =
{
.llseek = virtdev_llseek,
.read = virtdev_read,
.write = virtdev_write,
.unlocked_ioctl = virtdev_ioctl,
.open = virtdev_open,
.release= virtdev_release,
};
static char *chardev_devnode(struct device *dev, umode_t *mode)
{
if (mode)
*mode = 0666;
return NULL;
}
static int __init lsadc_init(void)
{
int ret;
int err;
ret = alloc_chrdev_region(&devno, 0, 1, "lsadc");
lsadc_major = MAJOR(devno);
devp = kzalloc(sizeof(struct virtdev_dev), GFP_KERNEL);
cls = class_create(NULL, "lsadc");//第一个参数指定类的所有者是哪个模块,第二个参数指定类名。
dev = device_create(cls, NULL, devno, NULL, "lsadc");//第一个参数指定所要创建的设备所从属的类,
//第二个参数是这个设备的父设备,如果没有就指定为NULL,
cdev_init(&devp->cdev, &virtdev_fops);
devp->cdev.owner = THIS_MODULE;
err = cdev_add(&devp->cdev, devno, 1);
if (!request_mem_region(LSADC_RGG_BASE_ADDR, 52, "GPJ0BASE"))
return -EINVAL;
baseaddr = ioremap(LSADC_RGG_BASE_ADDR, 52);
writel(0xFFF004FF, LSADC_CTRL0);
writel(0x1, LSADC_CTRL4);
writel(0x1, LSADC_CTRL7);
return 0;
}
static void __exit lsadc_exit(void)
{
device_unregister(dev);
class_destroy(cls);
device_destroy(cls, devno);
cdev_del(&devp->cdev);
kfree(devp);
unregister_chrdev_region(devno,1);
iounmap(baseaddr);
release_mem_region(baseaddr, 52);
}
module_init(lsadc_init);
module_exit(lsadc_exit);
MODULE_AUTHOR("Public");
MODULE_LICENSE("GPL");
海思LSADC驱动源码,dv300等适用。
需积分: 14 22 浏览量
2022-08-12
13:28:17
上传
评论
收藏 22KB GZ 举报
天才2012
- 粉丝: 1072
- 资源: 41
评论0