[Feature][T8TSK-114]Initialize the gpio in the kernel

Change-Id: I8f75c3ff6769dbe92a0c4f655630844afe763153
diff --git a/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/auto2735evb.dts b/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/auto2735evb.dts
index 716549a..677f6bf 100755
--- a/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/auto2735evb.dts
+++ b/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/auto2735evb.dts
@@ -1511,6 +1511,10 @@
             "nfi_cg";
 #endif
 };
+/*Lxf add in 2022/12/2 for gpio init*/
+&gpio_init{
 
+};
+/*Lxf add in 2022/12/2 for gpio init end*/
 #include <mediatek/evb6890v1_64_cpe/cust.dtsi>
 /*End of this file, DO NOT ADD ANYTHING HERE*/
diff --git a/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/mt2735.dtsi b/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/mt2735.dtsi
index bb47281..7e172b6 100644
--- a/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/mt2735.dtsi
+++ b/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/mt2735.dtsi
@@ -4499,7 +4499,11 @@
         enable-active-high;
 	/*zhengzhou 0316 ---*/
     };
-
+/*Lxf add in 2022/12/2 for gpio init*/
+	gpio_init: gpio_init{
+		compatible = "linux,gpio_init";
+	};
+/*Lxf add in 2022/12/2 for gpio init end*/
 	firmware {
 		optee {
 			compatible = "linaro,optee-tz";
diff --git a/src/kernel/linux/v4.19/drivers/Makefile b/src/kernel/linux/v4.19/drivers/Makefile
index a4c433d..6066d60 100644
--- a/src/kernel/linux/v4.19/drivers/Makefile
+++ b/src/kernel/linux/v4.19/drivers/Makefile
@@ -5,7 +5,9 @@
 # 15 Sep 2000, Christoph Hellwig <hch@infradead.org>
 # Rewritten to use lists instead of if-statements.
 #
-
+#Lxf add in 2022/12/2 for gpio init
+obj-y				+= lynq_gpio_init/
+#Lxf add in 2022/12/2 for gpio init end
 obj-y				+= irqchip/
 obj-y				+= bus/
 
diff --git a/src/kernel/linux/v4.19/drivers/lynq_gpio_init/Makefile b/src/kernel/linux/v4.19/drivers/lynq_gpio_init/Makefile
new file mode 100644
index 0000000..0f7ff3d
--- /dev/null
+++ b/src/kernel/linux/v4.19/drivers/lynq_gpio_init/Makefile
@@ -0,0 +1,2 @@
+
+obj-y	+= lynq_gpio_init.o
diff --git a/src/kernel/linux/v4.19/drivers/lynq_gpio_init/lynq_gpio_init.c b/src/kernel/linux/v4.19/drivers/lynq_gpio_init/lynq_gpio_init.c
new file mode 100755
index 0000000..e7caba3
--- /dev/null
+++ b/src/kernel/linux/v4.19/drivers/lynq_gpio_init/lynq_gpio_init.c
@@ -0,0 +1,71 @@
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+
+#include "../pinctrl/mediatek/pinctrl-mtk-common-v2_debug.h"
+#include "../pinctrl/mediatek/pinctrl-mtk-common-v2.h"
+#include "lynq_gpio_init.h"
+
+
+static int __init drv_init(void)
+{
+    struct device_node *gpio_device_node = NULL;
+    struct device_node *gpio_next_node = NULL;
+    int ret = 0;
+    int i;
+
+    printk("GPIO_INIT:init start");
+    log_offset = sprintf(log_info, "GPIO init start\n");
+    //create folder in /sys
+	ret = kobject_init_and_add(&kobj,&ktype,NULL,"lynq_gpio");
+    ret = kobject_init_and_add(&kobj_log,&ktype_log,NULL,"lynq_log");
+    //find the dts node
+    gpio_device_node = of_find_node_by_path("/gpio_init");
+    if(gpio_device_node == NULL)
+    {
+        printk("GPIO_INIT: get DTS property failed!\n");
+        log_offset += sprintf(log_info + log_offset, "get DTS property failed!\n");
+        return 0;
+    }
+    //get the number of gpio_init child node
+    node_num = of_get_child_count(gpio_device_node);
+    if(node_num <= GPIO_NODE_NUM)
+    {
+        printk("GPIO_INIT:node number: %d", node_num);
+        log_offset += sprintf(log_info + log_offset, "GPIO_INIT:node number: %d\n", node_num);
+    }
+    else
+    {
+        node_num = GPIO_NODE_NUM;
+        log_offset += sprintf(log_info + log_offset, "GPIO_INIT:over the max number\n");
+        printk("GPIO_INIT:over the max number");
+    }
+//set each gpio
+   for(i = 0; i < node_num; i++)
+   {
+        gpio_next_node = of_get_next_child(gpio_device_node, gpio_next_node);
+        if(gpio_next_node)
+        {
+            printk("exist this node");
+        }
+        else
+        {
+            printk("no more node");
+            break;
+        }
+        ret = set_gpio(gpio_next_node, i);        
+    }
+
+    printk("GPIO_INIT:END");
+    log_offset += sprintf(log_info + log_offset, "GPIO_INIT:END\n");
+    return 0;
+}
+
+device_initcall(drv_init);
+MODULE_AUTHOR("Mobiletek");
+MODULE_DESCRIPTION("driver for init gpio");
+MODULE_LICENSE("GPL");
diff --git a/src/kernel/linux/v4.19/drivers/lynq_gpio_init/lynq_gpio_init.h b/src/kernel/linux/v4.19/drivers/lynq_gpio_init/lynq_gpio_init.h
new file mode 100755
index 0000000..1d58455
--- /dev/null
+++ b/src/kernel/linux/v4.19/drivers/lynq_gpio_init/lynq_gpio_init.h
@@ -0,0 +1,315 @@
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/kobject.h>
+#include <linux/platform_device.h>
+#include <linux/device.h> 
+#include <linux/string.h> 
+#include <linux/sysfs.h> 
+#include <linux/stat.h> 
+#include <linux/slab.h>
+
+#include "../pinctrl/mediatek/pinctrl-mtk-common-v2_debug.h"
+#include "../pinctrl/mediatek/pinctrl-mtk-common-v2.h"
+
+#define GPIO_NODE_NUM 15
+#define LOG_SIZE 8192
+#define ERROR_SIZE 1024 
+
+struct gpio_node{
+    int gpio_num;
+	int gpio_mode;
+	int gpio_dir;
+	int gpio_dout;
+	int gpio_din;
+};
+
+//struct gpio_node *gpio_test;
+
+struct mtk_pinctrl *hw = NULL;
+const struct mtk_pin_desc *desc = NULL;
+
+struct kobject kobj;
+struct kobject kobj_log;
+int node_num = 0;
+struct gpio_node gpio_node_list[GPIO_NODE_NUM];
+
+char log_info[LOG_SIZE];
+int log_offset = 0;
+char error_info[ERROR_SIZE];
+int error_offset = 0;
+ 
+ssize_t kobj_test_show(struct kobject *kobject, struct attribute *attr,char *buf);
+ssize_t kobj_log_show(struct kobject *kobject, struct attribute *attr,char *buf);
+int set_gpio(struct device_node *gpio_node, int num);
+
+struct attribute gpio_attr = { 
+	.name = "gpio_init", 
+	.mode = S_IRUGO, 
+}; 
+struct attribute gpio_attr_log = { 
+	.name = "gpio_init_log", 
+	.mode = S_IRUGO, 
+}; 
+static struct attribute *def_attrs[] = { 
+	&gpio_attr, 
+	NULL, 
+}; 
+static struct attribute *def_attrs_log[] = { 
+	&gpio_attr_log, 
+	NULL, 
+}; 
+
+struct sysfs_ops obj_test_sysops = 
+{ 
+	.show = kobj_test_show, 
+}; 
+ 
+struct sysfs_ops gpio_log_sysops = 
+{ 
+	.show = kobj_log_show, 
+}; 
+ 
+struct kobj_type ktype =  
+{ 
+	.sysfs_ops=&obj_test_sysops, 
+	.default_attrs=def_attrs, 
+};
+ 
+struct kobj_type ktype_log =  
+{ 
+	.sysfs_ops=&gpio_log_sysops, 
+	.default_attrs=def_attrs_log, 
+};
+ 
+/*cat /sys/lynq_gpio/gpio_init*/ 
+ssize_t kobj_test_show(struct kobject *kobject, struct attribute *attr,char *buf)
+{
+    int show;
+    int i;
+	printk("gpio config show.\n"); 
+	printk("attrname:%s, node_num: %d.\n", attr->name, node_num); 
+	show = sprintf(buf,"%s, node_num: %d\n",attr->name, node_num);
+    show += sprintf(buf + show, "%s", error_info);
+    show += sprintf(buf + show, "NUM\tMODE\tDIR\tDOUT\tDIN\n");
+    for(i = 0; i < node_num; i++)
+    {
+        show += sprintf(buf + show, "%d\t%d\t%d\t%d\t%d\n", gpio_node_list[i].gpio_num, gpio_node_list[i].gpio_mode, gpio_node_list[i].gpio_dir, gpio_node_list[i].gpio_dout, gpio_node_list[i].gpio_din);
+        printk("%d\t%d\t%d\t%d\t%d\n", gpio_node_list[i].gpio_num, gpio_node_list[i].gpio_mode, gpio_node_list[i].gpio_dir, gpio_node_list[i].gpio_dout, gpio_node_list[i].gpio_din);
+    }
+    return strlen(buf);
+}
+/*cat /sys/lynq_log/gpio_init_log*/
+ssize_t kobj_log_show(struct kobject *kobject, struct attribute *attr,char *buf)
+{
+	printk("gpio init log show.\n"); 
+    sprintf(buf,"SHOW LOG\n%s", log_info);
+    return strlen(buf);
+}
+int set_gpio(struct device_node *gpio_node, int num)
+{
+    int ret = 0;
+    unsigned int gpio_num, gpio_mode, gpio_dir, gpio_dout, gpio_din;
+    int read_mode = -1;
+
+    gpio_node_list[num].gpio_num = -1;
+    gpio_node_list[num].gpio_mode = -1;
+    gpio_node_list[num].gpio_dir = -1;
+    gpio_node_list[num].gpio_din = -1;
+    gpio_node_list[num].gpio_dout = -1;
+
+    //get the gpio hw
+    ret = of_property_read_u32(gpio_node, "gpio_num", &gpio_num);
+    if(ret == -EINVAL || ret == -ENODATA)
+    {
+        printk("no value or no node");
+        log_offset += sprintf(log_info + log_offset,"No gpio num\n");
+        return 0;
+    }
+    else if(ret < 0)
+    {
+        printk("GPIO_INIT:READ ERROR: %d", ret);
+        log_offset += sprintf(log_info + log_offset, "GPIO_INIT: read num ERROR: %d\n", ret);
+        return ret;
+    }
+
+    gpio_node_list[num].gpio_num = (int)gpio_num;
+    printk("GPIO_INIT: the gpio_num is %u", gpio_num);
+    log_offset += sprintf(log_info + log_offset, "GPIO_INIT: the gpio_num is %u\n", gpio_num);
+
+    hw = mtk_gpio_find_mtk_pinctrl_dev_hw();
+    if(hw == NULL)
+    {
+        printk("GPIO_INIT: GET HW ERROR!");
+        log_offset += sprintf(log_info + log_offset, "GPIO_INIT: can not find this gpiochip!\n");
+        return -1;
+    }
+	if (gpio_num > hw->soc->npins)
+    {
+        log_offset += sprintf(log_info + log_offset, "GPIO_INIT: ERROR: over the max gpio num!\n");
+        error_offset += sprintf(error_info + error_offset, "GPIO_INIT: ERROR: over the max gpio num!\n");
+        return -1;
+    }
+    desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio_num];
+    //end of get gpio hw   
+
+//set gpio mode
+    ret = of_property_read_u32(gpio_node, "gpio_mode", &gpio_mode);
+    if(ret == -EINVAL || ret == -ENODATA)
+    {
+        printk("no value or no node");
+        log_offset += sprintf(log_info + log_offset, "no value or no node\n");
+    }
+    else if(ret < 0)
+    {
+        printk("GPIO_INIT:READ ERROR: %d", ret);
+        log_offset += sprintf(log_info + log_offset, "GPIO_INIT: read num ERROR: %d\n", ret);
+        return ret;
+    }
+    else
+    {
+        gpio_node_list[num].gpio_mode = (int)gpio_mode;
+        printk("GPIO_INIT: the gpio_mode is %u", gpio_mode);
+        log_offset += sprintf(log_info + log_offset, "GPIO_INIT: the gpio_mode is %u\n", gpio_mode);
+        if(gpio_mode >= 0 && gpio_mode <= 7)
+        {
+            ret = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE, gpio_mode);
+            if(ret == 0)
+            {
+                ret = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_MODE, &read_mode);
+                log_offset += sprintf(log_info + log_offset, "GPIO_INIT: Mode SET %d\n", read_mode);
+                printk("GPIO_INIT: modify successfully"); 
+            }
+            else
+            {
+                printk("GPIO_INIT: SET REEOR %d", ret);
+                log_offset += sprintf(log_info + log_offset, "GPIO_INIT: SET REEOR %d\n", ret);
+                return ret;
+            }
+        }
+        else
+        {
+            log_offset += sprintf(log_info + log_offset, "GPIO_INIT: mode: %u out of the range 0-7\n", gpio_mode);
+            error_offset += sprintf(error_info + error_offset, "GPIO_INIT: mode: %u out of the range 0-7\n", gpio_mode);
+        }
+    }
+//set gpio dir
+    ret = of_property_read_u32(gpio_node, "gpio_dir", &gpio_dir);
+    if(ret == -EINVAL || ret == -ENODATA)
+    {
+        printk("no value or no node");
+        log_offset += sprintf(log_info + log_offset, "no value or no node\n");
+    }
+    else if(ret < 0)
+    {
+        printk("GPIO_INIT:READ ERROR: %d", ret);
+        log_offset += sprintf(log_info + log_offset, "GPIO_INIT: read num ERROR: %d\n", ret);
+        return ret;
+    }
+    else
+    {
+        gpio_node_list[num].gpio_dir = (int)gpio_dir;
+        printk("GPIO_INIT: the gpio_dir is %u", gpio_dir);
+        log_offset += sprintf(log_info + log_offset, "GPIO_INIT: the gpio_dir is %u\n", gpio_dir);
+        if(gpio_dir == 0 || gpio_dir == 1)
+        {
+            ret = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, gpio_dir);
+            if(ret == 0)
+            {
+                printk("GPIO_INIT: modify successfully"); 
+            }
+            else
+            {
+                printk("GPIO_INIT: SET REEOR %d", ret);
+                log_offset += sprintf(log_info + log_offset, "GPIO_INIT: SET REEOR %d\n", ret);
+                return ret;
+            }
+        }
+        else
+        {
+            log_offset += sprintf(log_info + log_offset, "GPIO_INIT: dir: %u out of the range 0-1\n", gpio_dir);
+            error_offset += sprintf(error_info + error_offset, "GPIO_INIT: dir: %u out of the range 0-1\n", gpio_dir);
+        }
+	    
+    }    
+//set gpio dout
+    ret = of_property_read_u32(gpio_node, "gpio_dout", &gpio_dout);
+    if(ret == -EINVAL || ret == -ENODATA)
+    {
+        printk("no value or no node");
+        log_offset += sprintf(log_info + log_offset, "no value or no node\n");
+    }
+    else if(ret < 0)
+    {
+        printk("GPIO_INIT:READ ERROR: %d", ret);
+        log_offset += sprintf(log_info + log_offset, "GPIO_INIT: read num ERROR: %d\n", ret);
+        return ret;
+    }
+    else
+    {
+        gpio_node_list[num].gpio_dout = (int)gpio_dout;
+        printk("GPIO_INIT: the gpio_dout is %u", gpio_dout);
+        log_offset += sprintf(log_info + log_offset, "GPIO_INIT: the gpio_dout is %u\n", gpio_dout);
+        if(gpio_dout == 0 || gpio_dout == 1)
+        {
+            ret = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO, gpio_dout);
+            if(ret == 0)
+            {
+                printk("GPIO_INIT: modify successfully"); 
+            }
+            else
+            {
+                printk("GPIO_INIT: SET REEOR %d", ret);
+                log_offset += sprintf(log_info + log_offset, "GPIO_INIT: SET REEOR %d\n", ret);
+                return ret;
+            }
+        }
+        else
+        {
+            log_offset += sprintf(log_info + log_offset, "GPIO_INIT: dout: %u out of the range 0-1\n", gpio_dout);
+            error_offset += sprintf(error_info + error_offset, "GPIO_INIT: dout: %u out of the range 0-1\n", gpio_dout);
+        }
+    }
+//set gpio din
+    ret = of_property_read_u32(gpio_node, "gpio_din", &gpio_din);
+    if(ret == -EINVAL || ret == -ENODATA)
+    {
+        printk("no value or no node");
+        log_offset += sprintf(log_info + log_offset, "no value or no node\n");
+    }
+    else if(ret < 0)
+    {
+        printk("GPIO_INIT:READ ERROR: %d", ret);
+        log_offset += sprintf(log_info + log_offset, "GPIO_INIT: read num ERROR: %d\n", ret);
+        return ret;
+    }
+    else
+    {
+        gpio_node_list[num].gpio_din = (int)gpio_din;
+        printk("GPIO_INIT: the gpio_din is %u", gpio_din);
+        log_offset += sprintf(log_info + log_offset, "GPIO_INIT: the gpio_din is %u\n", gpio_din);
+        if(gpio_din == 0 || gpio_din == 1)
+        {
+            ret = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DI, gpio_din);
+            if(ret == 0)
+            {
+                printk("GPIO_INIT: modify successfully"); 
+            }
+            else
+            {
+                printk("GPIO_INIT: SET REEOR %d", ret);
+                log_offset += sprintf(log_info + log_offset, "GPIO_INIT: SET REEOR %d\n", ret);
+                return ret;
+            }
+        }
+        else
+        {
+            log_offset += sprintf(log_info + log_offset, "GPIO_INIT: din: %u out of the range 0-1\n", gpio_din);
+            error_offset += sprintf(error_info + error_offset, "GPIO_INIT: din: %u out of the range 0-1\n", gpio_din);
+        }
+    }
+    return ret;
+}
diff --git a/src/kernel/linux/v4.19/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2_debug.c b/src/kernel/linux/v4.19/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2_debug.c
old mode 100644
new mode 100755
index 47c97dc..732260c
--- a/src/kernel/linux/v4.19/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2_debug.c
+++ b/src/kernel/linux/v4.19/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2_debug.c
@@ -29,6 +29,9 @@
 #include <linux/uaccess.h>
 #include <linux/io.h>
 //zhengzhou modify 20201110 end
+/*Lxf add in 2022/12/2 for gpio init*/
+#include "pinctrl-mtk-common-v2.h"
+/*Lxf add in 2022/12/2 for gpio init end*/
 //zhengzhou modify 20201110 start start
 struct mtk_pinctrl *hw_file ;//= dev_get_drvdata(dev);
 struct device *dev_file;
@@ -66,7 +69,33 @@
 
 	pr_notice("[pinctrl]cannot find %s gpiochip\n", pinctrl_paris_modname);
 }
+/*Lxf add in 2022/12/2 for gpio init*/
+struct mtk_pinctrl* mtk_gpio_find_mtk_pinctrl_dev_hw(void)
+{
+	struct gpio_desc *gdesc;
+	unsigned int pin = ARCH_NR_GPIOS - 1;
 
+	do {
+		gdesc = gpio_to_desc(pin);
+		if (gdesc
+		 && !strncmp(pinctrl_paris_modname,
+				gdesc->gdev->chip->label,
+				strlen(pinctrl_paris_modname))) {
+			g_hw = gpiochip_get_data(gdesc->gdev->chip);
+			
+			return g_hw;
+		}
+		if (gdesc)
+			pin = (pin + 1) - gdesc->gdev->chip->base;
+		if (pin == 0 || !gdesc)
+			break;
+	} while (1);
+
+	pr_notice("[pinctrl]cannot find %s gpiochip\n", pinctrl_paris_modname);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(mtk_gpio_find_mtk_pinctrl_dev_hw);
+/*Lxf add in 2022/12/2 for gpio init end*/
 int gpio_get_tristate_input(unsigned int pin)
 {
 	struct mtk_pinctrl *hw = NULL;
diff --git a/src/kernel/linux/v4.19/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2_debug.h b/src/kernel/linux/v4.19/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2_debug.h
old mode 100644
new mode 100755
index 5227f59..2c97de8
--- a/src/kernel/linux/v4.19/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2_debug.h
+++ b/src/kernel/linux/v4.19/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2_debug.h
@@ -5,10 +5,14 @@
  * Author: Light Hsieh <light.hsieh@mediatek.com>
  *
  */
-
+/*Lxf add in 2022/12/2 for gpio init*/
+#include "pinctrl-mtk-common-v2.h"
+/*Lxf add in 2022/12/2 for gpio init end*/
 #ifndef __PINCTRL_MTK_COMMON_V2_DEBUG_H
 #define __PINCTRL_MTK_COMMON_V2_DEBUG_H
 
 int gpio_get_tristate_input(unsigned int pin);
-
+/*Lxf add in 2022/12/2 for gpio init*/
+struct mtk_pinctrl* mtk_gpio_find_mtk_pinctrl_dev_hw(void);
+/*Lxf add in 2022/12/2 for gpio init end*/
 #endif /* __PINCTRL_MTK_COMMON_V2_DEBUG_H */