/********************************************************************************* * Copyright: (C) 2017 LingYun IoT Studio * All rights reserved. * * Filename: s3c_led.c * Description: This file * * Version: 1.0.0(07/26/2012~) * Author: Guo Wenxue * ChangeLog: 1, Release initial version on "07/26/2012 10:03:40 PM" * ********************************************************************************/ #include /* Every Linux kernel module must include this head */ #include /* Every Linux kernel module must include this head */ #include /* printk() */ #include /* struct fops */ #include /* error codes */ #include /* cdev_alloc() */ #include /* ioremap() */ #include /* request_mem_region() */ #include /* Linux kernel space head file for macro _IO() to generate ioctl command */ #include /* Define log level KERN_DEBUG */ #define LED_NUM 4 #define DISABLE 0 #define ENABLE 1 #define GPIO_INPUT 0x00 #define GPIO_OUTPUT 0x01 #define PLATDRV_MAGIC 0x60 #define LED_OFF _IO (PLATDRV_MAGIC, 0x18) #define LED_ON _IO (PLATDRV_MAGIC, 0x19) #define S3C_GPB_BASE 0x56000010 #define S3C_GPB_LEN 0x10 /* 0x56000010~0x56000020 */ #define GPBCON_OFFSET 0 #define GPBDAT_OFFSET 4 #define GPBUP_OFFSET 8 static void __iomem *gpbbase = NULL; #define read_reg32(addr) *(volatile unsigned int *)(addr) #define write_reg32(addr, val) *(volatile unsigned int *)(addr) = (val) int led[LED_NUM] = {5,6,8,10}; /* Four LEDs use GPB5,GPB6,GPB8,GPB10 */ int dev_count = ARRAY_SIZE(led); int dev_major = 0; int dev_minor = 0; int debug = DISABLE; static struct cdev *led_cdev; static int s3c_hw_init(void) { int i; unsigned int regval; if(!request_mem_region(S3C_GPB_BASE, S3C_GPB_LEN, "s3c2440 led")) { printk(KERN_ERR "request_mem_region failure!\n"); return -EBUSY; } if( !(gpbbase=(unsigned int *)ioremap(S3C_GPB_BASE, S3C_GPB_LEN)) ) { release_mem_region(S3C_GPB_BASE, S3C_GPB_LEN); printk(KERN_ERR "release_mem_region failure!\n"); return -ENOMEM; } for(i=0; iprivate_data = (void *)minor; printk(KERN_DEBUG "/dev/led%d opened.\n", minor); return 0; } static int led_release(struct inode *inode, struct file *file) { printk(KERN_DEBUG "/dev/led%d closed.\n", iminor(inode)); return 0; } static void print_help(void) { printk("Follow is the ioctl() commands for led driver:\n"); printk("Turn LED on command : %u\n", LED_ON); printk("Turn LED off command : %u\n", LED_OFF); return; } static long led_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int which = (int)file->private_data; switch (cmd) { case LED_ON: turn_led(which, LED_ON); break; case LED_OFF: turn_led(which, LED_OFF); break; default: printk(KERN_ERR "LED driver don't support ioctl command=%d\n", cmd); print_help(); break; } return 0; } static struct file_operations led_fops = { .owner = THIS_MODULE, .open = led_open, .release = led_release, .unlocked_ioctl = led_ioctl, }; static int __init s3c_led_init(void) { int result; dev_t devno; if( 0 != s3c_hw_init() ) { printk(KERN_ERR "s3c2440 LED hardware initialize failure.\n"); return -ENODEV; } /* Alloc the device for driver */ if (0 != dev_major) /* Static */ { devno = MKDEV(dev_major, 0); result = register_chrdev_region (devno, dev_count, "led"); } else { result = alloc_chrdev_region(&devno, dev_minor, dev_count, "led"); dev_major = MAJOR(devno); } /* Alloc for device major failure */ if (result < 0) { printk(KERN_ERR "S3C led driver can't use major %d\n", dev_major); return -ENODEV; } printk(KERN_DEBUG "S3C led driver use major %d\n", dev_major); if(NULL == (led_cdev=cdev_alloc()) ) { printk(KERN_ERR "S3C led driver can't alloc for the cdev.\n"); unregister_chrdev_region(devno, dev_count); return -ENOMEM; } led_cdev->owner = THIS_MODULE; cdev_init(led_cdev, &led_fops); result = cdev_add(led_cdev, devno, dev_count); if (0 != result) { printk(KERN_INFO "S3C led driver can't reigster cdev: result=%d\n", result); goto ERROR; } printk(KERN_ERR "S3C led driver[major=%d] version 1.0.0 installed successfully!\n", dev_major); return 0; ERROR: printk(KERN_ERR "S3C led driver installed failure.\n"); cdev_del(led_cdev); unregister_chrdev_region(devno, dev_count); return result; } static void __exit s3c_led_exit(void) { dev_t devno = MKDEV(dev_major, dev_minor); s3c_hw_term(); cdev_del(led_cdev); unregister_chrdev_region(devno, dev_count); printk(KERN_ERR "S3C led driver version 1.0.0 removed!\n"); return ; } /* These two functions defined in */ module_init(s3c_led_init); module_exit(s3c_led_exit); module_param(debug, int, S_IRUGO); module_param(dev_major, int, S_IRUGO); MODULE_AUTHOR("guowenxue@LingYun IoT Studio"); MODULE_DESCRIPTION("FL2440 LED linux lowlevel API driver"); MODULE_LICENSE("GPL");