/* beepdrv.c
TP-6000's beep driver. GUANGZHOU ZHIYUAN
Copyright (c) 2006 GUANGZHOU ZHIYUAN ELECTRONICS CO.LTD
By Chenxibing
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/arch/hardware.h>
#include <asm/uaccess.h>
#include <asm/arch/irq.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#include <mach/hardware.h>
#include <mach/platform.h>
#include <asm/arch/lpc32xx_gpio.h>
#include "beepdrv.h"
#define DEV_NAME "beep"
#define GPIO_IOBASE io_p2v(GPIO_BASE)
static struct semaphore beep_sem;
static int tp_beep_open(struct inode *inode, struct file *filp)
{
__raw_writel(_BIT(7), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_07
try_module_get(THIS_MODULE);
printk( KERN_INFO DEV_NAME " opened!\n");
return 0;
}
static int tp_beep_release(struct inode *inode, struct file *filp)
{
__raw_writel(_BIT(7), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_07
module_put(THIS_MODULE);
printk(KERN_INFO DEV_NAME " released!\n");
return 0;
}
static ssize_t tp_beep_write(struct file *filp, const char __user *buff, size_t count, loff_t *ppos)
{
int i;
unsigned char ctrl=0;
if (count > 1) {
return -EFBIG;
}
if (down_interruptible(&beep_sem))
return -ERESTARTSYS;
get_user(ctrl, (u8 *)buff);
// printk("write date ctrl=0x%0x\n", ctrl);
i = (ctrl-0x30)&0x03;
if(i==0) {
__raw_writel(_BIT(7), GPIO_P3_OUTP_CLR(GPIO_IOBASE));//CLR GPIO_07
} else {
__raw_writel(_BIT(7), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_07
}
up(&beep_sem);
return count;
}
static int tp_beep_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
int level;
if (_IOC_TYPE(cmd) != BEEP_IOC_MAGIC) {
return -ENOTTY;
}
if (_IOC_NR(cmd) >= BEEP_IOC_MAXNR) {
return -ENOTTY;
}
// printk("arg=0x%x\n", arg);
switch (cmd) {
case SET_BEEP_ON:
//printk("BEEP_ON\n");
__raw_writel(_BIT(7), GPIO_P3_OUTP_CLR(GPIO_IOBASE));//CLR GPIO_07
udelay(10);
break;
case SET_BEEP_OFF:
//printk("BEEP_OFF\n");
__raw_writel(_BIT(7), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_07
udelay(10);
break;
default:
__raw_writel(_BIT(7), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_07
break;
}
return 0;
}
static struct file_operations tp_beep_fops = {
.owner = THIS_MODULE,
.write = tp_beep_write,
.ioctl = tp_beep_ioctl,
.open = tp_beep_open,
.release = tp_beep_release,
};
static struct miscdevice tp_beep_miscdev =
{
.minor = MISC_DYNAMIC_MINOR,
.name = DEV_NAME,
.fops = &tp_beep_fops,
};
static int tp_beep_probe(struct device *dev)
{
int ret;
printk(KERN_INFO DEV_NAME " probing...\n");
ret = misc_register(&tp_beep_miscdev);
if (ret)
printk(KERN_ERR "Failed to register miscdev.\n");
return ret;
}
static int tp_beep_remove(struct device *dev)
{
misc_deregister(&tp_beep_miscdev);
printk(KERN_INFO DEV_NAME " removed!\n");
return 0;
}
struct platform_device *tp_beep_device;
static struct device_driver tp_beep_driver = {
.name = DEV_NAME,
.owner = THIS_MODULE,
.bus = &platform_bus_type,
.probe = tp_beep_probe,
.remove = tp_beep_remove,
};
static int __init tp_beep_init(void)
{
int rc = 0;
int i;
printk(KERN_INFO DEV_NAME " init...\n");
for(i=0; i<4; i++) {
// s3c2410_beep_cfgpin(BEEP01[i], BEEP01_OUTP[i]);
// s3c2410_beep_pullup(BEEP01[i], 0); //enable pullup
// s3c2410_beep_setpin(BEEP01[i], 1); //default all HIGH
}
__raw_writel(_BIT(7), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_07
tp_beep_device = platform_device_register_simple(DEV_NAME, -1, NULL, 0);
if(IS_ERR(tp_beep_device)) {
goto out;
}
rc = driver_register(&tp_beep_driver);
if (rc < 0) {
platform_device_unregister(tp_beep_device);
}
sema_init(&beep_sem, 1);
out:
return rc;
}
static void __exit tp_beep_exit(void)
{
__raw_writel(_BIT(7), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_07
printk(KERN_INFO DEV_NAME " init...\n");
driver_unregister(&tp_beep_driver);
platform_device_unregister(tp_beep_device);
printk(KERN_INFO "tp_beep exit!\n");
}
module_init(tp_beep_init);
module_exit(tp_beep_exit);
MODULE_AUTHOR("Abing ");
MODULE_DESCRIPTION("ZHIYUAN tp-beep Driver");
MODULE_LICENSE("GPL");
|