]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
drivers:misc: Loki Gamepad reset driver
authorAnkita Garg <ankitag@nvidia.com>
Fri, 14 Nov 2014 01:11:12 +0000 (17:11 -0800)
committerRaymond Poudrier <rapoudrier@nvidia.com>
Fri, 6 Feb 2015 17:58:13 +0000 (09:58 -0800)
Bug 1560517

Change-Id: I6542a1f8c8d4df94823a8b2104be13809a59ed2f
Signed-off-by: Ankita Garg <ankitag@nvidia.com>
Reviewed-on: http://git-master/r/603010
(cherry picked from commit a354e5bb16fdc3f5ee9a2096ece28cbcb7f03850)
Reviewed-on: http://git-master/r/665941
GVS: Gerrit_Virtual_Submit
Reviewed-by: Raymond Poudrier <rapoudrier@nvidia.com>
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/nv_gamepad_reset.c [new file with mode: 0644]

index 5641738c1af771cb6aa9e02911f58f7961e50bd8..9f7a293476f492962cfd796d885d952dc8d96f3e 100644 (file)
@@ -662,6 +662,11 @@ config TEGRA_PROC_POWER_MODEL
          A simple model of processor power relating voltage, frequency,
          cores, and chip specific data. Used by various drivers.
 
+config NV_GAMEPAD_RESET
+       tristate "Nvidia Gamepad Reset Driver"
+       help
+        This driver provides an interface that can be used to recover
+        gamepad uC when needed
 
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
index b7e8156dfdc60e8eb0d2d2406172707762fdbe67..373ec0feb42b7de6b802a1cfd3ef4d52bc43c21f 100644 (file)
@@ -88,4 +88,4 @@ obj-$(CONFIG_ARCH_TEGRA)        +=tegra_timerinfo.o
 obj-$(CONFIG_MODS)             += mods/
 obj-$(CONFIG_DENVER_CPU)       += idle_test_t132.o
 obj-$(CONFIG_TEGRA_PROC_POWER_MODEL) += tegra_ppm.o
-
+obj-$(CONFIG_NV_GAMEPAD_RESET) += nv_gamepad_reset.o
diff --git a/drivers/misc/nv_gamepad_reset.c b/drivers/misc/nv_gamepad_reset.c
new file mode 100644 (file)
index 0000000..716e6cd
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * NVIDIA Gamepad Reset Driver for NVIDIA Shield-2
+ *
+ * Copyright (c) 2014, NVIDIA Corporation. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+#define DRIVER_AUTHOR "Ankita Garg, ankitag@nvidia.com"
+#define DRIVER_DESC "NVIDIA Shield Gamepad Reset Driver"
+
+#define RESET_DELAY    25
+
+struct gamepad_info {
+       int reset_gpio;
+};
+
+#ifndef CONFIG_OF
+struct gamepad_rst_platform_data {
+       int reset_gpio;
+};
+#endif
+
+static ssize_t set_gamepad_reset(struct device *dev,
+               struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       int ret;
+       struct gamepad_info *data = dev_get_drvdata(dev);
+       int gamepad_rst_gpio = data->reset_gpio;
+       long unsigned int value;
+
+       if (kstrtoul(buf, 10, &value))
+               return count;
+
+       if (!value)
+               return count;
+
+       ret = gpio_request(gamepad_rst_gpio, "GAMEPAD_RST");
+       if (ret < 0) {
+               dev_err(dev, "%s: gpio_request failed %d\n", __func__, ret);
+               return ret;
+       }
+
+       ret = gpio_direction_output(gamepad_rst_gpio, 1);
+       if (ret < 0) {
+               gpio_free(gamepad_rst_gpio);
+               dev_err(dev, "%s: gpio_direction_output failed %d\n",
+                       __func__, ret);
+               return ret;
+       }
+
+       gpio_set_value(gamepad_rst_gpio, 0);
+       udelay(RESET_DELAY);
+       gpio_set_value(gamepad_rst_gpio, 1);
+       gpio_free(gamepad_rst_gpio);
+
+       dev_dbg(dev, "%s: done\n", __func__);
+
+       return count;
+}
+
+static DEVICE_ATTR(gamepad_reset, S_IWUSR | S_IWGRP, NULL, set_gamepad_reset);
+
+static int gamepad_reset_remove(struct platform_device *pdev)
+{
+       device_remove_file(&pdev->dev, &dev_attr_gamepad_reset);
+       return 0;
+}
+
+static int gamepad_reset_probe(struct platform_device *pdev)
+{
+       int ret;
+       u32 value;
+       struct device *dev = &pdev->dev;
+       struct gamepad_info *data;
+#ifdef CONFIG_OF
+       struct device_node *node = pdev->dev.of_node;
+
+       if (!node) {
+               pr_err("gamepad_reset: dev of node NULL\n");
+               return -EINVAL;
+       }
+
+       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+       if (!data) {
+               pr_err("gamepad_reset: Failed to allocate memory\n");
+               return -ENOMEM;
+       }
+
+       ret = of_property_read_u32(node, "reset_gpio", &value);
+       if (ret) {
+               pr_err("gamepad_reset: dev of_property_read failed\n");
+               return -EIO;
+       }
+       data->reset_gpio = (int)value;
+#else
+       struct gamepad_rst_platform_data *pdata = pdev->dev.platform_data;
+
+       if (!pdata)
+               return -EINVAL;
+
+       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+       if (!data) {
+               pr_err("gamepad_reset: Failed to allocate memory\n");
+               return -ENOMEM;
+       }
+       data->reset_gpio = pdata->reset_gpio;
+#endif
+
+       platform_set_drvdata(pdev, data);
+
+       ret = device_create_file(dev, &dev_attr_gamepad_reset);
+       if (ret)
+               dev_err(dev, "Failed to create gamepad reset file\n");
+
+       dev_info(dev, "gamepad_reset: probed successfully\n");
+       return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id of_gamepad_reset_match[] = {
+       { .compatible = "loki-gamepad-reset", },
+       {},
+};
+#endif
+
+static struct platform_driver gamepad_reset_driver = {
+       .probe = gamepad_reset_probe,
+       .remove = gamepad_reset_remove,
+       .driver = {
+               .name = "gamepad_reset",
+               .owner = THIS_MODULE,
+#ifdef CONFIG_OF
+               .of_match_table = of_gamepad_reset_match,
+#endif
+       }
+};
+
+static int __init gamepad_reset_init(void)
+{
+       int ret;
+
+       ret = platform_driver_register(&gamepad_reset_driver);
+       if (ret < 0)
+               pr_err("%s: Failed to register gamepad_reset driver\n",
+                       __func__);
+
+       return ret;
+}
+
+static void __exit gamepad_reset_exit(void)
+{
+       platform_driver_unregister(&gamepad_reset_driver);
+}
+
+module_init(gamepad_reset_init);
+module_exit(gamepad_reset_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");