#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/device.h> #include <asm/io.h> #include <asm/arch/regs-gpio.h> #include <asm/hardware.h> #include <asm/uaccess.h>
#define DEVICE_NAME "drv_leds"
static int major; static struct class *leds_class; static struct class_device *leds_class_devs[4];
static unsigned long gpio_base;
#define GPIO_OFFSET(addr) ((addr) - 0x56000000) #define GPFCON (*(volatile unsigned long *)(gpio_base + GPIO_OFFSET(0x56000050))) #define GPFDAT (*(volatile unsigned long *)(gpio_base + GPIO_OFFSET(0x56000054)))
static int drv_leds_open(struct inode *inode, struct file *file) { int minor = MINOR(inode->i_rdev);
if ((minor == 1) || (minor == 0)) { GPFCON &= ~(0x3<<(4*2)); GPFCON |= (1<<(4*2)); GPFDAT |= (1<<4); } if ((minor == 2) || (minor == 0)) { GPFCON &= ~(0x3<<(5*2)); GPFCON |= (1<<(5*2)); GPFDAT |= (1<<5); } if ((minor == 3) || (minor == 0)) { s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP); s3c2410_gpio_setpin(S3C2410_GPF6, 1); } printk("drv_leds_open\n"); return 0; }
static ssize_t drv_leds_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { int minor = MINOR(file->f_dentry->d_inode->i_rdev); char val;
copy_from_user(&val, data, 1);
if ((minor == 1) || (minor == 0)) { if (val) GPFDAT &= ~(1<<4); else GPFDAT |= (1<<4); } if ((minor == 2) || (minor == 0)) { if (val) GPFDAT &= ~(1<<5); else GPFDAT |= (1<<5); } if ((minor == 3) || (minor == 0)) { s3c2410_gpio_setpin(S3C2410_GPF6, !val); } printk("drv_leds_write, led%d=%d\n", minor, val); return len; }
static struct file_operations drv_leds_fops = { .owner = THIS_MODULE, .open = drv_leds_open, .write = drv_leds_write, };
static int drv_leds_init(void) { int minor;
gpio_base = ioremap(0x56000000, 0xD0); if (!gpio_base) { return -EIO; }
major = register_chrdev(0, DEVICE_NAME, &drv_leds_fops);
leds_class = class_create(THIS_MODULE, "leds"); if (IS_ERR(leds_class)) return PTR_ERR(leds_class);
leds_class_devs[0] = class_device_create(leds_class, NULL, MKDEV(major, 0), NULL, "leds");
for (minor = 1; minor < 4; minor++) { leds_class_devs[minor] = class_device_create(leds_class, NULL, MKDEV(major, minor), NULL, "led%d", minor); if (unlikely(IS_ERR(leds_class_devs[minor]))) return PTR_ERR(leds_class_devs[minor]); }
printk(DEVICE_NAME " initialized\n"); return 0; }
static void drv_leds_exit(void) { int minor;
for (minor = 0; minor < 4; minor++) { class_device_unregister(leds_class_devs[minor]); } class_destroy(leds_class);
unregister_chrdev(major, DEVICE_NAME); iounmap(gpio_base); printk(DEVICE_NAME " deinitialized\n"); }
module_init(drv_leds_init); module_exit(drv_leds_exit);
MODULE_AUTHOR("draapho"); MODULE_VERSION("0.1.1"); MODULE_DESCRIPTION("First Driver for LED"); MODULE_LICENSE("GPL");
|