#include <linux/kernel.h>//printk
#include <linux/module.h>//MODULE_LICENSE
#include <linux/fs.h> //MKDEV register_chrdev_region unregister_chrdev_region
#include <linux/cdev.h>// cdev_init cdev_add cdev_del
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/device.h>
#include "head.h"
MODULE_LICENSE("GPL");
#define CHRDEV_MAROR 300
#define CHRDEV_MINOR 0
#define NUM_OF_DEVICE 1
#define GPD0CON 0X114000A0
#define TCFG0 0X139D0000
dev_t devno;
struct cdev cdev;
char data[128] ;
volatile unsigned int *gpd0con;
volatile unsigned int *tcfg0;
volatile unsigned int *tcfg1;
volatile unsigned int *tcon;
volatile unsigned int *tcntb0;
volatile unsigned int *tcmpb0;
struct class *cls;
static int fs4412_beep_open (struct inode *inode, struct file *file)
{
printk("fs4412_beep_open \n");
return 0;
}
static ssize_t fs4412_beep_read (struct file *file, char __user *buf, size_t size, loff_t *loff)
{
int ret;
if(size > 128)
size = 128;
if(size < 0)
return -ENOMEM;
ret = copy_to_user(buf,data,size);
if(0 != ret)
{
printk("copy_to_user fail \n");
return -EAGAIN;
}
printk("fs4412_beep_read \n");
return 0;
}
static int fs4412_beep_release (struct inode *inode, struct file *file)
{
printk("fs4412_beep_release \n");
return 0;
}
static ssize_t fs4412_beep_write (struct file *file, const char __user *buf, size_t size, loff_t *loff)
{
int ret;
if(size > 128)
size = 128;
if(size < 0)
return -ENOMEM;
ret = copy_from_user(data,buf,size);
if(0 != ret)
{
printk("copy_to_user fail \n");
return -EAGAIN;
}
printk("data1 = %s\n",data);
printk("fs4412_beep_write \n");
return 0;
}
static long fs4412_beep_ioctl (struct file *file, unsigned int cmd, unsigned long arg)
{
switch(cmd)
{
case BEEP_ON:
*tcon = (*tcon &~(0xf <<0))|(0x9 <<0);
break;
case BEEP_OFF:
*tcon = (*tcon &~(0xf <<0))&~(0x9 <<0);
break;
}
return 0;
}
struct file_operations fs4412_beep_fops = {
.owner = THIS_MODULE,
.open = fs4412_beep_open,
.read = fs4412_beep_read,
.write = fs4412_beep_write,
.unlocked_ioctl = fs4412_beep_ioctl,
.release = fs4412_beep_release,
};
/*function:入口函数
* param: void
* return: int
* */
int chrdev_init(void)
{
int ret;
//1.申请设备号
devno = MKDEV(CHRDEV_MAROR,CHRDEV_MINOR);
//2.注册设备号
ret = register_chrdev_region(devno,NUM_OF_DEVICE,"duang");
if(0 != ret)
{
printk("register_chrdev_region fail \n");
return -EBUSY;
}
//3.初始化cdev
//4.将cdev结构体添加到系统中
cdev_add(&cdev,devno,NUM_OF_DEVICE);
cdev_init(&cdev,&fs4412_beep_fops);
gpd0con = ioremap(GPD0CON,0x4);
if(NULL == gpd0con)
{
printk("ioremap fail \n");
goto err1;
}
tcfg0 = ioremap(TCFG0,0x10);
if(NULL == tcfg0)
{
printk("ioremap tcfg0 \n");
goto err2;
}
tcfg1 = tcfg0 +1;
tcon = tcfg0 +2;
tcntb0 = tcfg0 +3;
tcmpb0 = tcfg0 +4;
*gpd0con = (*gpd0con &~(0xf <<0))|(0x2 <<0);
*tcfg0 = (*tcfg0 &~(0xff <<0))|(0xff <<0);
*tcfg1 = (*tcfg1 &~(0xf <<0))|(0x2 <<0);
*tcntb0 = *tcntb0 |500;
*tcmpb0 = *tcmpb0 |250;
*tcon = (*tcon &~(0xf <<0))|(0x2 <<0);
*tcon = (*tcon &~(0xf <<0))&~(0x9 <<0);
cls = class_create(THIS_MODULE,"beep");
device_create(cls,NULL,devno,NULL,"pwm");
printk("chrdev_init \n");
return 0;
err2:
iounmap(gpd0con);
err1:
cdev_del(&cdev);
unregister_chrdev_region(devno,NUM_OF_DEVICE);
return ret;
}
/*function: 出口函数
* param:void
* return:int
* */
void chrdev_exit(void)
{
device_destroy(cls,devno);
class_destroy(cls);
iounmap(gpd0con);
iounmap(tcfg0);
cdev_del(&cdev);
unregister_chrdev_region(devno,NUM_OF_DEVICE);
printk("chrdev_exit \n");
}
module_init(chrdev_init);
module_exit(chrdev_exit );