#include <linux/types.h> #include <linux/kernel.h> #include <linux/delay.h> #include <linux/ide.h>
#include <linux/init.h> #include <linux/module.h>
#include <linux/errno.h> #include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h> #include <linux/of_address.h>
#include <asm/mach/map.h> #include <asm/uaccess.h> #include <asm/io.h>
#define DEV_CNT 1 #define DEV_NAME "mydtsled" #define DEV_CLASS "mydtsled_class" #define DEV_DEVICE "mydtsled_device"
static void __iomem *IMX6U_CCM_CCGR1; static void __iomem *SW_MUX_GPIO1_IO03; static void __iomem *SW_PAD_GPIO1_IO03; static void __iomem *GPIO1_DR; static void __iomem *GPIO1_GDIR;
struct led { dev_t devid; int major; int minor;
struct cdev _cdev;
struct class * _class; struct device * _device;
struct device_node * _dtb_node; } mydtsled;
static int led_open(struct inode *inode, struct file *filp) { printk("led is open!\r\n"); filp->private_data = &mydtsled; return 0; }
static ssize_t led_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt) { printk("mytest read!\r\n"); return 0; }
#define LEDOFF 0 #define LEDON 1
static void led_switch(u8 sta) { u32 val = 0; if(sta == LEDON) { val = readl(GPIO1_DR); val &= ~(1 << 3); writel(val, GPIO1_DR); }else if(sta == LEDOFF) { val = readl(GPIO1_DR); val|= (1 << 3); writel(val, GPIO1_DR); } }
static ssize_t led_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt) { int retvalue = 0; unsigned char databuf[1];
printk("mydtsled write! : filp->private_data->major = %d\r\n", (*(struct led *)(filp->private_data)).major); retvalue = copy_from_user(databuf, buf, cnt); if(retvalue < 0){ printk("kernel get user write failed\n"); return -EFAULT; } else { printk("kernel get user char = %s\n", buf); }
if(databuf[0] == LEDON){ led_switch(LEDON); } else if(databuf[0] == LEDOFF) { led_switch(LEDOFF); }
return 0; }
static int led_release(struct inode *inode, struct file *filp) { printk("chrdevbase release!\r\n"); 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 dtsled_init(void){ struct property* prop; int ret; const char * str; u32 regdata[14];
printk("my dts led driver start init\n");
mydtsled._dtb_node = of_find_node_by_path("/led@0"); if(mydtsled._dtb_node == NULL){ printk("not find dtb node\n"); return -EINVAL; } else { printk("find node\n"); }
prop = of_find_property(mydtsled._dtb_node , "compatible", NULL); if(prop == NULL){ printk("not find dtb compatible\n"); } else { printk("compatible = %s\n", (char*)(prop->value)); }
ret = of_property_read_string(mydtsled._dtb_node , "status", &str); if(ret < 0){ printk("status read failed\n"); } else { printk("status = %s\n", str); }
ret = of_property_read_u32_array(mydtsled._dtb_node, "reg", regdata, 10); if(ret < 0){ printk("reg read failed\n"); } else { u8 i = 0; printk("read reg = \n"); for(i = 0; i<10; i++) printk("%x ", regdata[i]); printk("\n"); }
IMX6U_CCM_CCGR1 = of_iomap(mydtsled._dtb_node, 0); SW_MUX_GPIO1_IO03 = of_iomap(mydtsled._dtb_node, 1); SW_PAD_GPIO1_IO03 = of_iomap(mydtsled._dtb_node, 2); GPIO1_DR = of_iomap(mydtsled._dtb_node, 3); GPIO1_GDIR = of_iomap(mydtsled._dtb_node, 4); u32 val = 0; val = readl(IMX6U_CCM_CCGR1); val &= ~(3<<26); val |= (3<<26); writel(val, IMX6U_CCM_CCGR1);
writel(5, SW_MUX_GPIO1_IO03); writel(0x10B0, SW_PAD_GPIO1_IO03);
val = readl(GPIO1_GDIR); val &= ~(1<<3); val |= (1<<3); writel(val, GPIO1_GDIR);
val = readl(GPIO1_DR); val |= (1<<3); writel(val, GPIO1_DR);
alloc_chrdev_region(&(mydtsled.devid), 0, DEV_CNT, DEV_NAME); mydtsled.major = MAJOR(mydtsled.devid); mydtsled.minor = MINOR(mydtsled.devid); printk("mydtsled alloc devid over, major = %d, minor = %d\n", mydtsled.major, mydtsled.minor);
mydtsled._cdev.owner = THIS_MODULE; cdev_init(&(mydtsled._cdev), &led_fops); cdev_add(&(mydtsled._cdev), mydtsled.devid, DEV_CNT);
mydtsled._class = class_create(THIS_MODULE, DEV_CLASS); mydtsled._device = device_create(mydtsled._class, NULL, mydtsled.devid, NULL, DEV_DEVICE);
printk("my dts led driver init over\n"); return 0; }
static void __exit dtsled_exit(void){ printk("my dts led driver start exit\n");
unregister_chrdev_region(mydtsled.devid, DEV_CNT); cdev_del(&(mydtsled._cdev));
device_destroy(mydtsled._class, mydtsled.devid); class_destroy(mydtsled._class);
printk("my dts led driver exit over\n"); }
module_init(dtsled_init); module_exit(dtsled_exit);
MODULE_LICENSE("GPL"); MODULE_AUTHOR("liangji");
|