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);