zte's code,first commit

Change-Id: I9a04da59e459a9bc0d67f101f700d9d7dc8d681b
diff --git a/ap/os/linux/linux-3.4.x/drivers/gpio/gpio_zx29.c b/ap/os/linux/linux-3.4.x/drivers/gpio/gpio_zx29.c
new file mode 100755
index 0000000..8dcf3c3
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/gpio/gpio_zx29.c
@@ -0,0 +1,388 @@
+/* Copyright (c) 2013, ZTE-TSP. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+#include <asm/mach/irq.h>
+
+#include <mach/gpio.h>
+#include <mach/pcu.h>
+#include <mach/irqs.h>
+
+
+static int zx29_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	unsigned int gpio=chip->base+offset;
+	int ret=0;
+
+	ret = zx29_gpio_input_data(gpio);
+
+	return ret;
+}
+
+static void zx29_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+	unsigned int gpio=chip->base+offset;
+
+	zx29_gpio_output_data(gpio,(unsigned int)val);
+}
+
+static int zx29_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	unsigned int gpio=chip->base+offset;
+	
+    zx29_gpio_set_direction(gpio, GPIO_IN);
+	
+	return 0;
+}
+
+static int zx29_gpio_direction_output(struct gpio_chip *chip,
+  									unsigned offset,
+  									int val)
+{
+	unsigned int gpio=chip->base+offset;
+	
+    zx29_gpio_set_direction(gpio, GPIO_OUT);
+	zx29_gpio_output_data(gpio, (unsigned int)val);
+	
+	return 0;
+}
+
+
+static int zx29_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	unsigned int gpio=chip->base+offset;
+	
+	return (zx29_gpio2irq(gpio));  
+}
+
+
+static struct gpio_chip zx29_gpio = 
+{
+		.base             = BASE_GPIO,
+		.ngpio            = NGPIO,
+		.direction_input  = zx29_gpio_direction_input,
+		.direction_output = zx29_gpio_direction_output,
+		.get              = zx29_gpio_get,
+		.set              = zx29_gpio_set,
+		.to_irq           = zx29_gpio_to_irq,
+		.request          = NULL,
+		.free             = NULL,
+};
+
+/*
+  * select gpio multiplex function
+  * gpio:  		gpio number
+  * func:   PIN_FUNC_SEL_AON/PIN_FUNC_SEL_PD   
+  *		according with register defination
+  */
+int zx29_gpio_config(unsigned int gpio, gpio_func_id func )
+{
+	return zx29_gpio_function_sel(gpio, func);
+}
+EXPORT_SYMBOL(zx29_gpio_config);
+
+#if 0
+/*add by shideyou 20130731*/
+static ssize_t ap_ufi_wps_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	long value;
+	unsigned int tmp = 0;
+	unsigned int dir = 0;
+    
+    struct zx29_gpio_platform_data *pdata = dev->platform_data;
+    dir = zx29_gpio_get_direction(pdata->ufi_wps);
+    tmp = zx29_gpio_function_sel_get(pdata->ufi_wps);
+    tmp = ((tmp>>24)&0x7);
+    if((tmp==0)||(tmp==2)||(tmp==4)||(tmp==6))
+    {
+    	value = gpio_get_value(pdata->ufi_wps);
+    	if (value < 0)
+    	    return value;
+
+  	  if (value) 
+	  	if(dir)
+   	     		strcpy(buf, "input highlevel!\n");
+		else
+			strcpy(buf, "output highlevel!\n");
+   	 else
+	 	if(dir)
+   	     		strcpy(buf, "input lowlevel!\n");
+		else
+			strcpy(buf, "output lowlevel!\n");
+	  return 18;
+    }
+    else
+    {
+	    strcpy(buf, "it is not gpio!\n");
+	    return 16;
+    }
+}
+static const DEVICE_ATTR(ap_ufi_wps, 0600, ap_ufi_wps_show, NULL);
+
+static ssize_t ap_ufi_reset_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	long value;
+    	unsigned int tmp = 0;
+	unsigned int dir = 0;
+		
+    struct zx29_gpio_platform_data *pdata = dev->platform_data;
+	dir = zx29_gpio_get_direction(pdata->ufi_resetkey);
+    tmp = zx29_gpio_function_sel_get(pdata->ufi_resetkey);
+    tmp = ((tmp>>24)&0x3);
+    if((tmp==0)||(tmp==2)||(tmp==3))
+    {
+    	value = gpio_get_value(pdata->ufi_resetkey);
+   	 if (value < 0)
+   	     return value;
+
+  	  if (value)   
+     	   	if(dir)
+   	     		strcpy(buf, "input highlevel!\n");
+		else
+			strcpy(buf, "output highlevel!\n");
+   	 else
+	 	if(dir)
+   	     		strcpy(buf, "input lowlevel!\n");
+		else
+			strcpy(buf, "output lowlevel!\n");
+	  return 18;
+    }
+    else
+    {
+	strcpy(buf, "it is not gpio!\n");
+	return 16;
+    }   
+}
+static const DEVICE_ATTR(ap_ufi_reset, 0600, ap_ufi_reset_show, NULL);
+
+static ssize_t ap_poweron_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	long value;
+    unsigned int tmp = 0;
+	unsigned int dir = 0;
+	
+    struct zx29_gpio_platform_data *pdata = dev->platform_data;
+	dir = zx29_gpio_get_direction(pdata->power_on_int);
+	tmp = zx29_gpio_function_sel_get(pdata->power_on_int);
+    tmp = ((tmp>>24)&0x7);
+    if((tmp==0)||(tmp==2)||(tmp==3)||(tmp==4)||(tmp==6))
+    {
+   	 value = gpio_get_value(pdata->power_on_int);
+  	  if (value < 0)
+   	     return value;
+
+  	  if (value)   
+   	     if(dir)
+   	     		strcpy(buf, "input highlevel!\n");
+		else
+			strcpy(buf, "output highlevel!\n");
+   	 else
+	 	if(dir)
+   	     		strcpy(buf, "input lowlevel!\n");
+		else
+			strcpy(buf, "output lowlevel!\n");
+	  return 18;
+    	}
+	else
+	{
+		strcpy(buf, "it is not gpio!\n");
+		return 16;
+	}    
+}
+static const DEVICE_ATTR(ap_poweron, 0600, ap_poweron_show, NULL);
+
+static ssize_t ap_wifi_hostwake_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	long value;
+    unsigned int tmp = 0;
+	unsigned int dir = 0;
+	
+    struct zx29_gpio_platform_data *pdata = dev->platform_data;
+	dir = zx29_gpio_get_direction(pdata->wifi_host_wake);
+	tmp = zx29_gpio_function_sel_get(pdata->wifi_host_wake);
+    tmp = ((tmp>>24)&0x7);
+    if((tmp==0)||(tmp==2)||(tmp==4)||(tmp==6))
+    {
+	    value = gpio_get_value(pdata->wifi_host_wake);
+	    if (value < 0)
+		return value;
+
+    	    if (value)   
+		if(dir)
+   	     		strcpy(buf, "input highlevel!\n");
+		else
+			strcpy(buf, "output highlevel!\n");
+   	 else
+	 	if(dir)
+   	     		strcpy(buf, "input lowlevel!\n");
+		else
+			strcpy(buf, "output lowlevel!\n");
+	  return 18;
+    	}
+	else
+	{
+		strcpy(buf, "it is not gpio!\n");
+		return 16;
+	}
+           	
+}
+static const DEVICE_ATTR(ap_wifi_hostwake, 0600, ap_wifi_hostwake_show, NULL);
+
+static ssize_t ap_charger_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	long value;
+    unsigned int tmp = 0;
+	unsigned int dir = 0;
+	
+    struct zx29_gpio_platform_data *pdata = dev->platform_data;
+	dir = zx29_gpio_get_direction(pdata->charger_pg);
+	tmp = zx29_gpio_function_sel_get(pdata->charger_pg);
+    tmp = ((tmp>>24)&0x3);
+    if((tmp==0)||(tmp==2))
+    {
+    	value = gpio_get_value(pdata->charger_pg);
+    	if (value < 0)
+       		return value;
+
+    	if (value)   
+        	if(dir)
+   	     		strcpy(buf, "input highlevel!\n");
+		else
+			strcpy(buf, "output highlevel!\n");
+   	 else
+	 	if(dir)
+   	     		strcpy(buf, "input lowlevel!\n");
+		else
+			strcpy(buf, "output lowlevel!\n");
+	  return 18;
+    }
+    else
+    {
+	strcpy(buf, "it is not gpio!\n");
+	return 16;
+    }
+}
+static const DEVICE_ATTR(ap_charger, 0600, ap_charger_show, NULL);
+#endif
+
+static const struct attribute *ap_gpio_attrs[] = {
+#if 0
+	&dev_attr_ap_ufi_reset.attr,
+	&dev_attr_ap_poweron.attr,
+	&dev_attr_ap_ufi_wps.attr,
+	&dev_attr_ap_wifi_hostwake.attr,
+	&dev_attr_ap_charger.attr,
+#endif	
+	NULL,
+};
+
+static const struct attribute_group ap_gpio_attr_group = {
+	.attrs = (struct attribute **) ap_gpio_attrs,
+};
+
+static int __init zx29_gpio_probe(struct platform_device *dev)
+{
+	int ret;
+
+	zx29_gpio.label = dev->name;
+	ret = gpiochip_add(&zx29_gpio);
+	if (ret < 0)
+		return ret;
+	
+	pr_info("[GPIO]create sysfs interface\n");
+	ret = sysfs_create_group(&dev->dev.kobj, &ap_gpio_attr_group);
+	if (ret)
+	   printk(KERN_WARNING "[GPIO]sysfs_create_group ret %d\n", ret);
+
+	return 0;
+}
+
+static int zx29_gpio_remove(struct platform_device *dev)
+{
+	int ret = gpiochip_remove(&zx29_gpio);
+
+	if (ret) {
+		dev_err(&dev->dev, "%s failed, %d\n",
+				"gpiochip_remove()", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct platform_driver zx29_gpio_driver = {
+	.driver = {
+		.name  = "zx29_gpio",
+		.owner = THIS_MODULE,
+	},
+	.probe  = zx29_gpio_probe,
+	.remove = __devexit_p(zx29_gpio_remove),
+};  
+
+static struct zx29_gpio_platform_data zx29_gpio_data=
+{
+	.ufi_resetkey 	= GPIO_UFI_RESETKEY,
+	.power_on_int 	= GPIO_POWER_ON_INT,
+	.ufi_wps 		= GPIO_UFI_WPS,
+	.wifi_host_wake = GPIO_WIFI_HOST_WAKE,
+	.charger_pg		= GPIO_CHARGER_PG,
+};
+
+static struct platform_device zx29_device_gpio = 
+{
+	.name = "zx29_gpio",
+	.id   = -1,
+	.dev = {
+		.platform_data = &zx29_gpio_data,
+	},
+};
+
+static int __init zx29_gpio_init(void)
+{
+	int rc;
+
+	rc = platform_driver_register(&zx29_gpio_driver);
+	if (!rc) {
+		rc = platform_device_register(&zx29_device_gpio);
+		if (rc)
+			platform_driver_unregister(&zx29_gpio_driver);
+	}
+    if(!rc)
+		pr_info("[GPIO]zx29 GPIO initialized\n");
+	
+	return rc;
+}
+
+static void __exit zx29_gpio_exit(void)
+{
+	platform_device_unregister(&zx29_device_gpio);
+	platform_driver_unregister(&zx29_gpio_driver);
+}
+
+postcore_initcall(zx29_gpio_init);
+module_exit(zx29_gpio_exit);