/** * @:0xf4028004和0xf4028008是GPIO端口3输出与输出寄存器虚拟地址 * 地址是我直接算出来的,可以用io_p2v()函数实现 * @: __raw_writel()向地址写数据 * @: class_create()创建总线,class_destroy()删除 * @: device_create()创建设备节点,device_destroy()删除 */
#include <linux/init.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/cdev.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/uaccess.h> #include <mach/irq.h> #include <asm/io.h> #include <asm/pgtable.h> #include <asm/page.h> #include <mach/hardware.h> #include <mach/platform.h> #include <mach/lpc32xx_gpio.h>
#define DEVNAME "LED" #define LED_MAJOR 251
#define P3_SET ((volatile unsigned int) 0xf4028004) #define P3_CLR ((volatile unsigned int) 0xf4028008)
struct led_dev { struct cdev cdev; unsigned int value; };
struct led_dev *led_dev;
int led_open(struct inode *inode, struct file *filp) { struct led_dev *dev; dev = container_of(inode->i_cdev, struct led_dev, cdev); filp->private_data = dev; try_module_get(THIS_MODULE); return 0; }
int led_release(struct inode *inode, struct file *filp) { module_put(THIS_MODULE); return 0; }
static int led_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) { struct led_dev *dev = filp->private_data; if(copy_from_user(&(dev->value), buf , 1)) { return -EFAULT; } if(dev->value == 1) __raw_writel(1 << 5, P3_SET); else __raw_writel(1 << 5, P3_CLR); return 1; }
int led_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { struct led_dev *dev = filp->private_data; switch (cmd) { case 0: dev->value = 0; __raw_writel(1 << 5, P3_CLR); break; case 1: dev->value = 1; __raw_writel(1 << 5, P3_SET); break; default : dev->value = 1; __raw_writel(1 << 5, P3_SET); break; } return 0; }
struct file_operations led_fops = { .owner = THIS_MODULE, .write = led_write, .ioctl = led_ioctl, .open = led_open, .release = led_release, };
static void led_setup_cdev(struct led_dev *dev, int index) { int err, devno = MKDEV(LED_MAJOR, 0); cdev_init(&dev->cdev, &led_fops); dev->cdev.owner = THIS_MODULE; dev->cdev.ops = &led_fops; err = cdev_add(&dev->cdev, devno, 1); if(err) printk(KERN_NOTICE "Error adding LED"); }
struct class *led_class; static int __init led_init(void) { int i,result; dev_t dev = MKDEV(LED_MAJOR, 0); result = register_chrdev_region(dev, 1, DEVNAME); if(result < 0) return result; led_dev = kmalloc(sizeof(struct led_dev), GFP_KERNEL); if(!led_dev) { result = ~ENOMEM; goto fail; } memset(led_dev, 0, sizeof(struct led_dev)); led_setup_cdev(led_dev, 0); led_class = class_create(THIS_MODULE, "led_class"); device_create(led_class, NULL, MKDEV(LED_MAJOR, 0), "LED","LED%d", 0); __raw_writel(1 << 5, P3_SET); for(i = 0; i< 5; i++) { msleep(1000); } __raw_writel(1 << 5, P3_CLR); for(i = 0; i < 10; i++) { msleep(1000); } __raw_writel(1 << 5, P3_SET); return 0; fail: unregister_chrdev_region(dev, 1); return result; }
static void __exit led_exit(void) { cdev_del(&led_dev->cdev); device_destroy(led_class, MKDEV(LED_MAJOR, 0)); class_destroy(led_class); kfree(led_dev); unregister_chrdev_region(MKDEV(LED_MAJOR, 0), 1); }
module_init(led_init); module_exit(led_exit);
MODULE_LICENSE("GPL");
|