#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
#include <linux/gpio.h>
#include <asm/gpio.h>
#include <asm/delay.h>
#include <linux/clk.h>
#include <plat/gpio-cfg.h>


static int __x210_led_status[4] = { 0 };

static void __x210_led_probe(void)
{
int ret;

ret = gpio_request(S5PV210_GPJ0(3), "GPJ0");//注册gpio
if(ret < 0)
printk("x210-led: request gpio GPJ0(3) fail\n");
s3c_gpio_setpull(S5PV210_GPJ0(3), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S5PV210_GPJ0(3), S3C_GPIO_SFN(1));
gpio_set_value(S5PV210_GPJ0(3), 1);

ret = gpio_request(S5PV210_GPJ0(4), "GPJ0");
if(ret)
printk("x210-led: request gpio GPJ0(4) fail\n");
s3c_gpio_setpull(S5PV210_GPJ0(4), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S5PV210_GPJ0(4), S3C_GPIO_SFN(1));
gpio_set_value(S5PV210_GPJ0(4), 1);

ret = gpio_request(S5PV210_GPJ0(5), "GPJ0");
if(ret)
printk("x210-led: request gpio GPJ0(5) fail\n");
s3c_gpio_setpull(S5PV210_GPJ0(5), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S5PV210_GPJ0(5), S3C_GPIO_SFN(1));
gpio_set_value(S5PV210_GPJ0(5), 1);

ret = gpio_request(S5PV210_GPD0(1), "GPD0");
if(ret)
printk("x210-led: request gpio GPD0(1) fail\n");
s3c_gpio_setpull(S5PV210_GPD0(1), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S5PV210_GPD0(1), S3C_GPIO_SFN(1));
gpio_set_value(S5PV210_GPD0(1), 1);

__x210_led_status[0] = 0;//保存led的信息,为不亮
__x210_led_status[1] = 0;
__x210_led_status[2] = 0;
__x210_led_status[3] = 0;
}

static void __x210_led_remove(void)
{
gpio_free(S5PV210_GPJ0(3));//释放gpio
gpio_free(S5PV210_GPJ0(4));
gpio_free(S5PV210_GPJ0(5));
gpio_free(S5PV210_GPD0(1));
}
/************ /sys/devices/platform/ljj-x210-led/led1,led2,led3 文件的读 *************/
static ssize_t x210_led_read(struct device *dev, struct device_attribute *attr, char *buf)
{
if(!strcmp(attr->attr.name, "led1"))//判断是哪个文件
{
if(__x210_led_status[0] != 0)
return strlcpy(buf, "1\n", 3);
else
return strlcpy(buf, "0\n", 3);
}
else if(!strcmp(attr->attr.name, "led2"))
{
if(__x210_led_status[1] != 0)
return strlcpy(buf, "1\n", 3);
else
return strlcpy(buf, "0\n", 3);
}
else if(!strcmp(attr->attr.name, "led3"))
{
if(__x210_led_status[2] != 0)
return strlcpy(buf, "1\n", 3);
else
return strlcpy(buf, "0\n", 3);
}
else if(!strcmp(attr->attr.name, "led4"))
{
if(__x210_led_status[3] != 0)
return strlcpy(buf, "1\n", 3);
else
return strlcpy(buf, "0\n", 3);
}

return 0;
}
/************ /sys/devices/platform/ljj-x210-led/led1,led2,led3 文件的写 *************/
static ssize_t x210_led_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
unsigned long on = simple_strtoul(buf, NULL, 10);

if(!strcmp(attr->attr.name, "led1"))
{
if(on)
{
gpio_set_value(S5PV210_GPJ0(3), 0);
__x210_led_status[0] = 1;
}
else
{
gpio_set_value(S5PV210_GPJ0(3), 1);
__x210_led_status[0] = 0;
}
}
else if(!strcmp(attr->attr.name, "led2"))
{
if(on)
{
gpio_set_value(S5PV210_GPJ0(4), 0);
__x210_led_status[1] = 1;
}
else
{
gpio_set_value(S5PV210_GPJ0(4), 1);
__x210_led_status[1] = 0;
}
}
else if(!strcmp(attr->attr.name, "led3"))
{
if(on)
{
gpio_set_value(S5PV210_GPJ0(5), 0);
__x210_led_status[2] = 1;
}
else
{
gpio_set_value(S5PV210_GPJ0(5), 1);
__x210_led_status[2] = 0;
}
}
else if(!strcmp(attr->attr.name, "led4"))
{
if(on)
{
gpio_set_value(S5PV210_GPD0(1), 0);
__x210_led_status[3] = 1;
}
else
{
gpio_set_value(S5PV210_GPD0(1), 1);
__x210_led_status[3] = 0;
}
}

return count;
}

static DEVICE_ATTR(led1, 0666, x210_led_read, x210_led_write);//绑定led那几个文件的操作函数
static DEVICE_ATTR(led2, 0666, x210_led_read, x210_led_write);
static DEVICE_ATTR(led3, 0666, x210_led_read, x210_led_write);
static DEVICE_ATTR(led4, 0666, x210_led_read, x210_led_write);

static struct attribute * x210_led_sysfs_entries[] = {
&dev_attr_led1.attr,//绑定到文件中
&dev_attr_led2.attr, //参考
&dev_attr_led3.attr,
&dev_attr_led4.attr,
NULL,
};


static struct attribute_group x210_led_attr_group = {
.name = NULL,
.attrs = x210_led_sysfs_entries,
};

static int x210_led_probe(struct platform_device *pdev)
{
__x210_led_probe();

return sysfs_create_group(&pdev->dev.kobj, &x210_led_attr_group);
//把device ljj-x210-led 和led1,led2,led3绑定起来
//会在/sys/devices/platform/ljj-x210-led/ 下创建这几个文件
}

static int x210_led_remove(struct platform_device *pdev)
{
__x210_led_remove();

sysfs_remove_group(&pdev->dev.kobj, &x210_led_attr_group);//删除led那几个文件
return 0;
}

#ifdef CONFIG_PM
static int x210_led_suspend(struct platform_device *pdev, pm_message_t state)
{
return 0;
}

static int x210_led_resume(struct platform_device *pdev)
{
return 0;
}

#else
#define x210_led_suspend NULL
#define x210_led_resume NULL
#endif

static struct platform_driver x210_led_driver = {//驱动结构体
.probe = x210_led_probe,
.remove = x210_led_remove,
.suspend = x210_led_suspend,
.resume = x210_led_resume,
.driver = {
.name = "ljj-x210-led",
},
};

static struct platform_device x210_led_device = {//设备结构体
.name = "ljj-x210-led",
.id = -1,
};

static int __devinit x210_led_init(void)
{
int ret;

printk("x210 led driver\r\n");

ret = platform_device_register(&x210_led_device);//注册设备
if(ret)
printk("failed to register x210 led device\n");

ret = platform_driver_register(&x210_led_driver);//注册驱动
if(ret)
printk("failed to register x210 led driver\n");

return ret;
}

static void x210_led_exit(void)
{
platform_driver_unregister(&x210_led_driver);//注销设备
platform_device_unregister(&x210_led_device);//注销驱动
}

module_init(x210_led_init);
module_exit(x210_led_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("jianjun jiang <jerryjianjun@gmail.com>");
MODULE_DESCRIPTION("x210 led driver");

[root@liu driver_test]# cd /sys/bus/platform/devices/
[root@liu devices]# ls
ljj-x210-led                                    //其他省略
[root@liu devices]# cd ljj-x210-led/
[root@liu ljj-x210-led]# ls
driver     led2       led4       power      uevent
led1       led3       modalias   subsystem
[root@liu ljj-x210-led]# ls -l led*
-rw-rw-rw-    1 root     0             4096 Jan  1 12:01 led1
-rw-rw-rw-    1 root     0             4096 Jan  1 12:01 led2
-rw-rw-rw-    1 root     0             4096 Jan  1 12:01 led3
-rw-rw-rw-    1 root     0             4096 Jan  1 12:01 led4
[root@liu ljj-x210-led]# cat led1
0