#include #include #include #include #include #include #include #include #include #include #include #include #include "led.h" static dev_t devno = 0; static uint32_t led_major = LED_MAJOR; static uint32_t led_minor = 0; static struct class *led_class; static struct led_chrdev led_cdev[DEV_CNT] = { {.pa_dr = 0x0209C000,.pa_gdir = 0x0209C004,.pa_iomuxc_mux = 0x20E006C,.pa_ccm_ccgrx = 0x20C406C,.pa_iomux_pad = 0x20E02F8,.led_pin = 4,.clock_offset = 26}, {.pa_dr = 0x20A8000,.pa_gdir = 0x20A8004,.pa_iomuxc_mux = 0x20E01E0,.pa_ccm_ccgrx = 0x20C4074,.pa_iomux_pad = 0x20E046C,.led_pin = 20,.clock_offset = 12}, {.pa_dr = 0x20A8000,.pa_gdir = 0x20A8004,.pa_iomuxc_mux = 0x20E01DC,.pa_ccm_ccgrx = 0x20C4074,.pa_iomux_pad = 0x20E0468,.led_pin = 19,.clock_offset = 12}, }; static int led_open(struct inode *inode, struct file *filp) { uint32_t val = 0; struct led_chrdev *my_led_dev = NULL; PDEBUG("led open %d:%d...\n",MAJOR(inode->i_rdev),MINOR(inode->i_rdev)); my_led_dev = container_of(inode->i_cdev, struct led_chrdev, dev); filp->private_data = my_led_dev; my_led_dev->va_ccm_ccgrx = ioremap(my_led_dev->pa_ccm_ccgrx,4); my_led_dev->va_dr = ioremap(my_led_dev->pa_dr,4); my_led_dev->va_gdir = ioremap(my_led_dev->pa_gdir,4); my_led_dev->va_iomuxc_mux = ioremap(my_led_dev->pa_iomuxc_mux,4); my_led_dev->va_iomux_pad = ioremap(my_led_dev->pa_iomux_pad,4); val = ioread32(my_led_dev->va_ccm_ccgrx); val &= ~(3 << my_led_dev->clock_offset); val |= 3 << my_led_dev->clock_offset; iowrite32(val, my_led_dev->va_ccm_ccgrx); iowrite32(5, my_led_dev->va_iomuxc_mux); iowrite32(0x1F838, my_led_dev->va_iomux_pad); val = ioread32(my_led_dev->va_gdir); val &= ~(1 << my_led_dev->led_pin); val |= (1 << my_led_dev->led_pin); iowrite32(val, my_led_dev->va_gdir); val = ioread32(my_led_dev->va_dr); val |= (0x01 << my_led_dev->led_pin); iowrite32(val, my_led_dev->va_dr); return 0; } static ssize_t led_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt) { return cnt; } static ssize_t led_write(struct file *filp,const char __user *buf,size_t cnt, loff_t *offt) { uint32_t val = 0; uint32_t ret = 0; struct led_chrdev *my_led_dev = NULL; PDEBUG("led write...\n"); my_led_dev = filp->private_data; kstrtoul_from_user(buf,cnt,10,&ret); PDEBUG("ret = %u\n",ret); val = ioread32(my_led_dev->va_dr); if (ret) val &= ~(0x01 << my_led_dev->led_pin); else val |= (0x01 << my_led_dev->led_pin); iowrite32(val, my_led_dev->va_dr); *offt += cnt; return cnt; } static int led_release(struct inode *inode, struct file *filp) { struct led_chrdev *my_led_dev = NULL; my_led_dev = container_of(inode->i_cdev, struct led_chrdev, dev); iounmap(my_led_dev->va_ccm_ccgrx); iounmap(my_led_dev->va_dr); iounmap(my_led_dev->va_gdir); iounmap(my_led_dev->va_iomuxc_mux); iounmap(my_led_dev->va_iomux_pad); return 0; } static struct file_operations led_fops = { .owner = THIS_MODULE, .open = led_open, .read = led_read, .write = led_write, .release = led_release, }; static int __init my_led_init(void) { uint32_t ret = 0; uint32_t i = 0; dev_t cur_dev = 0; printk(KERN_INFO "led Module Init start\n"); if(led_major){ devno = MKDEV(led_major,led_minor); ret = register_chrdev_region(devno, DEV_CNT, "led"); } else{ ret = alloc_chrdev_region(&devno, 0, DEV_CNT, "led"); led_major = MAJOR(devno); } if(ret < 0){ printk(KERN_ERR "chrdev alloc region failed\n"); return ret; } printk(KERN_INFO "devno is %u(0x%x)(major:%u,minor:%u)\n",devno,devno,led_major,led_minor); led_class = class_create(THIS_MODULE, "led_class"); if(IS_ERR(led_class)) { printk(KERN_ERR" create class faild!/n"); return -EBUSY; } for(i = 0; i< DEV_CNT; i++) { cdev_init(&led_cdev[i].dev, &led_fops); led_cdev[i].dev.owner = THIS_MODULE; cur_dev = MKDEV(MAJOR(devno), MINOR(devno) + i); cdev_add(&led_cdev[i].dev, cur_dev, 1); device_create(led_class,NULL,cur_dev,NULL,"led_%s",(i == 0)?"red":((i == 1)? "green":"blue")); } return ret; } static void __exit my_led_exit(void) { uint32_t i = 0; dev_t cur_dev = 0; for(i =0 ; i < DEV_CNT; i++){ cur_dev = MKDEV(MAJOR(devno), MINOR(devno) + i); device_destroy(led_class,cur_dev); cdev_del(&led_cdev[i].dev); } class_destroy(led_class); if(!devno) unregister_chrdev_region(devno, DEV_CNT); printk("LED Module Exit\n"); } module_init(my_led_init); module_exit(my_led_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("liuchao");