#include <linux/module.h>
|
#include <linux/err.h>
|
#include <linux/gpio.h>
|
#include <linux/kernel.h>
|
#include <linux/of_gpio.h>
|
#include <linux/of_platform.h>
|
#include <linux/delay.h>
|
#include <linux/input.h>
|
#include <linux/proc_fs.h>
|
#include <linux/kernel.h>
|
#include <linux/init.h>
|
#include <asm/uaccess.h>
|
#include <linux/string.h>
|
#include <linux/uaccess.h>
|
#include <linux/device.h>
|
#include <linux/proc_fs.h>
|
|
#define GPIO_FUNCTION_OUTPUT 0
|
#define GPIO_FUNCTION_INPUT 1
|
#define GPIO_FUNCTION_RESET 3
|
#define HIGH "1"
|
#define LOW "0"
|
|
//static int flash_flag = 0;
|
|
struct ndj_gpio {
|
int gpio_num; //gpio num
|
int action; //gpio flag
|
int gpio_event; //input only
|
int send_mode; //input only
|
int gpio_function; //gpio function,i/o
|
int gpio_ctrl;
|
char *gpio_name;
|
};
|
|
struct ndj_gpio_data {
|
struct ndj_gpio ndj_gpio_num[20];
|
struct timer_list mytimer;
|
int gpio_dts_num;
|
unsigned int gpio_op0;
|
unsigned int gpio_op1;
|
};
|
|
static struct ndj_gpio_data *gpio_data = NULL;
|
|
/* creat sysfs gpio api node*/
|
#if 0
|
static ssize_t gpio_op0_show(struct class *class,struct class_attribute *attr, char *buf)
|
{
|
return sprintf(buf, "%d\n", gpio_get_value(gpio_data->gpio_op0));
|
}
|
|
static ssize_t gpio_op0_store(struct class *class,struct class_attribute *attr, const char *buf, size_t size)
|
{
|
if(!strncmp(buf, HIGH, strlen(HIGH))) {
|
gpio_set_value(gpio_data->gpio_op0, 1);
|
|
} else if(!strncmp(buf, LOW, strlen(LOW))) {
|
gpio_set_value(gpio_data->gpio_op0, 0);
|
}
|
return size;
|
}
|
|
static ssize_t gpio_op1_show(struct class *class,struct class_attribute *attr, char *buf)
|
{
|
return sprintf(buf, "%d\n", gpio_get_value(gpio_data->gpio_op1));
|
}
|
|
static ssize_t gpio_op1_store(struct class *class,struct class_attribute *attr, const char *buf, size_t size)
|
{
|
if(!strncmp(buf, HIGH, strlen(HIGH))) {
|
gpio_set_value(gpio_data->gpio_op1, 1);
|
|
} else if(!strncmp(buf, LOW, strlen(LOW))) {
|
gpio_set_value(gpio_data->gpio_op1, 0);
|
}
|
return size;
|
}
|
|
static CLASS_ATTR_RW(gpio_op0);
|
static CLASS_ATTR_RW(gpio_op1);
|
|
static struct attribute *ndj_gpio_attrs[] = {
|
&class_attr_gpio_op0.attr,
|
&class_attr_gpio_op1.attr,
|
NULL,
|
};
|
|
ATTRIBUTE_GROUPS(ndj_gpio);
|
|
/** Device model classes */
|
struct class ndj_io_class = {
|
.name = "io_control", //sysfs directory
|
.class_groups = ndj_gpio_groups,
|
};
|
|
#endif
|
//static int event_flag = 0;
|
static int open_now = 0;
|
static char* file_name = NULL;
|
|
static int gpio_open(struct inode *inode, struct file *file)
|
{
|
struct dentry* dent = file->f_path.dentry;
|
int i = 0;
|
|
file_name = (char*)(dent->d_name.name);
|
|
for (i = 0; i < gpio_data->gpio_dts_num; i++){
|
if(!strcmp(file_name,gpio_data->ndj_gpio_num[i].gpio_name)){
|
open_now = i;
|
}
|
}
|
return 0;
|
}
|
|
static ssize_t gpio_write(struct file *file, const char *buffer,size_t count, loff_t *data)
|
{
|
char buf[2]={0};
|
char s1[]="1";
|
|
if(copy_from_user(&buf[0],buffer,1)){
|
printk("failed to copy data to kernel space\n");
|
return -EFAULT;
|
}
|
|
if(!strcmp(buf,s1)){
|
gpio_direction_output(gpio_data->ndj_gpio_num[open_now].gpio_num,1);
|
//printk("%s write 1 succeed\n",gpio_data->ndj_gpio_num[open_now].gpio_name);
|
}else{
|
gpio_direction_output(gpio_data->ndj_gpio_num[open_now].gpio_num,0);
|
//printk("%s write 0 succeed\n",gpio_data->ndj_gpio_num[open_now].gpio_name);
|
}
|
return count;
|
}
|
|
|
static ssize_t gpio_read(struct file *file, char __user * buffer, size_t count, loff_t *data)
|
{
|
int gpio_val = 0;
|
int len = 0;
|
char s[10] = {0};
|
|
if(*data)
|
return 0;
|
|
gpio_val = gpio_get_value(gpio_data->ndj_gpio_num[open_now].gpio_num);
|
//printk("get %s value %d\n",gpio_data->ndj_gpio_num[open_now].gpio_name,gpio_val);
|
|
len = sprintf(s+len, "%d\n",gpio_val);
|
|
return simple_read_from_buffer(buffer, count, data, s, 2);
|
}
|
|
|
static const struct proc_ops gpio_ops = {
|
.proc_open = gpio_open,
|
.proc_write = gpio_write,
|
.proc_read = gpio_read,
|
};
|
|
static int ndj_gpio_probe(struct platform_device *pdev) {
|
struct device_node *np = pdev->dev.of_node;
|
struct device_node *child_np;
|
static struct proc_dir_entry *root_entry_gpio;
|
enum of_gpio_flags gpio_flags;
|
int ret = 0;
|
int gpio_cnt = 0;
|
char gpio_name_num[20];
|
int gpio_in_cnt = 0;
|
|
gpio_data = devm_kzalloc(&pdev->dev, sizeof(struct ndj_gpio_data),GFP_KERNEL);
|
if (!gpio_data) {
|
dev_err(&pdev->dev, "failed to allocate memory\n");
|
return -ENOMEM;
|
}
|
|
gpio_data->gpio_dts_num = of_get_child_count(np);
|
// printk("ndj_gpio prepare build %d gpio\n",gpio_data->gpio_dts_num);
|
|
if (gpio_data->gpio_dts_num == 0){
|
dev_info(&pdev->dev, "no gpio defined\n");
|
}
|
|
#if 0
|
/*gpio_op0*/
|
ret = of_get_named_gpio_flags(np, "gpio_op0", 0, &gpio_flags);
|
if (ret < 0) {
|
printk("%s() Can not read property gpio_op0\n", __func__);
|
return -ENODEV;
|
}
|
gpio_data->gpio_op0 = ret;
|
ret = gpio_request(gpio_data->gpio_op0, "gpio_op0");
|
if(ret < 0){
|
printk("%s() gpio_op0 request ERROR\n", __func__);
|
return -ENODEV;
|
}
|
|
gpio_direction_output(gpio_data->gpio_op0,!gpio_flags);
|
#endif
|
|
/* create node */
|
root_entry_gpio = proc_mkdir("ndj_gpio", NULL);
|
|
for_each_child_of_node(np, child_np)
|
{
|
/* parse dts */
|
gpio_data->ndj_gpio_num[gpio_cnt].gpio_num = of_get_named_gpio_flags(child_np, "gpio_num", 0, &gpio_flags);
|
if (!gpio_is_valid(gpio_data->ndj_gpio_num[gpio_cnt].gpio_num)){
|
return -1;
|
}
|
|
gpio_data->ndj_gpio_num[gpio_cnt].gpio_name = (char*)child_np -> name;
|
gpio_data->ndj_gpio_num[gpio_cnt].action = gpio_flags;
|
gpio_data->ndj_gpio_num[gpio_cnt].gpio_ctrl = gpio_cnt;
|
of_property_read_u32(child_np, "gpio_function", &(gpio_data->ndj_gpio_num[gpio_cnt].gpio_function));
|
|
// printk("ndj_gpio request %s\n",gpio_data->ndj_gpio_num[gpio_cnt].gpio_name);
|
|
|
switch(gpio_data->ndj_gpio_num[gpio_cnt].gpio_function) {
|
case GPIO_FUNCTION_INPUT : /* init input gpio */
|
ret = gpio_request(gpio_data->ndj_gpio_num[gpio_cnt].gpio_num, gpio_data->ndj_gpio_num[gpio_cnt].gpio_name);
|
if (ret < 0)
|
{
|
printk("gpio%d request error\n",gpio_data->ndj_gpio_num[gpio_cnt].gpio_num);
|
}else{
|
// printk("success request gpio %d in\n",gpio_data->ndj_gpio_num[gpio_cnt].gpio_num);
|
|
gpio_direction_input(gpio_data->ndj_gpio_num[gpio_cnt].gpio_num);
|
//gpio_direction_output(gpio_data->ndj_gpio_num[gpio_cnt].gpio_num,!gpio_data->ndj_gpio_num[gpio_cnt].action);
|
//event_flag = gpio_flags;
|
//of_property_read_u32(child_np, "send_mode", &(gpio_data->ndj_gpio_num[gpio_cnt].send_mode));
|
//of_property_read_u32(child_np, "gpio_event", &(gpio_data->ndj_gpio_num[gpio_cnt].gpio_event));
|
gpio_in_cnt++;
|
}
|
break;
|
|
case GPIO_FUNCTION_OUTPUT : /* init output gpio */
|
ret = gpio_request(gpio_data->ndj_gpio_num[gpio_cnt].gpio_num, gpio_data->ndj_gpio_num[gpio_cnt].gpio_name);
|
if (ret < 0){
|
printk("gpio%d request error\n",gpio_data->ndj_gpio_num[gpio_cnt].gpio_num);
|
//return ret;
|
}else{
|
gpio_direction_output(gpio_data->ndj_gpio_num[gpio_cnt].gpio_num,!gpio_data->ndj_gpio_num[gpio_cnt].action);
|
//printk("success request gpio%d out\n",gpio_data->ndj_gpio_num[gpio_cnt].gpio_num);
|
}
|
break;
|
|
case GPIO_FUNCTION_RESET :
|
ret = gpio_request(gpio_data->ndj_gpio_num[gpio_cnt].gpio_num, gpio_data->ndj_gpio_num[gpio_cnt].gpio_name);
|
if (ret < 0){
|
printk("gpio%d request error\n",gpio_data->ndj_gpio_num[gpio_cnt].gpio_num);
|
//return ret;
|
}else{
|
gpio_direction_output(gpio_data->ndj_gpio_num[gpio_cnt].gpio_num,gpio_data->ndj_gpio_num[gpio_cnt].action);
|
//printk("success request gpio%d reset\n",gpio_data->ndj_gpio_num[gpio_cnt].gpio_num);
|
mdelay(200);
|
gpio_direction_output(gpio_data->ndj_gpio_num[gpio_cnt].gpio_num,!gpio_data->ndj_gpio_num[gpio_cnt].action);
|
|
// gpio_cnt++;
|
}
|
break;
|
}
|
|
sprintf(gpio_name_num,gpio_data->ndj_gpio_num[gpio_cnt].gpio_name,gpio_cnt);
|
proc_create(gpio_name_num, 0666 , root_entry_gpio , &gpio_ops);
|
gpio_cnt++;
|
}
|
|
platform_set_drvdata(pdev, gpio_data);
|
|
#if 0
|
ret= class_register(&ndj_io_class);
|
if(ret < 0) {
|
return -EINVAL;
|
}
|
#endif
|
return 0;
|
}
|
|
|
static int ndj_gpio_suspend(struct platform_device *pdev, pm_message_t state)
|
{
|
// int ret;
|
// struct nk_io_pdata *pdata;
|
printk("nk_suspend !!!!\n");
|
return 0;
|
}
|
|
static int ndj_gpio_resume(struct platform_device *pdev)
|
{
|
// int ret,reset_pin;
|
printk("nk_io resume !!!!\n");
|
return 0;
|
}
|
|
|
static int ndj_gpio_remove(struct platform_device *pdev)
|
{
|
// class_unregister(&ndj_io_class);
|
return 0;
|
}
|
|
|
static const struct of_device_id ndj_gpio_of_match[] = {
|
{ .compatible = "nk_io_control" },
|
{ }
|
};
|
|
static struct platform_driver ndj_gpio_driver = {
|
.probe = ndj_gpio_probe,
|
.remove = ndj_gpio_remove,
|
.resume = ndj_gpio_resume,
|
.suspend = ndj_gpio_suspend,
|
.driver = {
|
.name = "nk_io_control",
|
.of_match_table = of_match_ptr(ndj_gpio_of_match),
|
},
|
};
|
|
module_platform_driver(ndj_gpio_driver);
|
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|