diff --git a/Documentation/devicetree/bindings/gpio/gpio-detection.txt b/Documentation/devicetree/bindings/gpio/gpio-detection.txt deleted file mode 100644 index 78bd530c8290..000000000000 --- a/Documentation/devicetree/bindings/gpio/gpio-detection.txt +++ /dev/null @@ -1,37 +0,0 @@ -Required properties: -- compatible: should be "gpio-detection" -- status: -- pinctrl-0 : phandle referencing pin configuration of the gpio controller -- pinctrl-names : a pinctrl state named "default" must be defined -- car-reverse : a describtion to show the gpio will be use to car reverse -- car-acc : a describtion to show the gpio will be use to car accelerate -- gpios : The GPIO to set high/low, see "gpios property" in - Documentation/devicetree/bindings/gpio/gpio.txt. If the pin should be - low to power down the board set it to "Active Low", otherwise set - gpio to "Active High". -- linux,debounce-ms: interrupt debounce time. (u32) -- label : The label / name for this partition. If omitted, the label is taken -- gpio,wakeup : To enable the wakeup comparator in probe - -Example: - - gpio_det: gpio-det { - compatible = "gpio-detection"; - status = "okay"; - - pinctrl-0 = <&gpio3_b1 &gpio3_b2>; - pinctrl-names = "default"; - car-reverse { - car-reverse-gpios = <&gpio3 10 GPIO_ACTIVE_HIGH>; - linux,debounce-ms = <5>; - label = "car-reverse"; - gpio,wakeup; - }; - - car-acc { - car-acc-gpios = <&gpio3 9 GPIO_ACTIVE_HIGH>; - linux,debounce-ms = <5>; - label = "car-acc"; - gpio,wakeup; - }; - }; diff --git a/drivers/misc/gpio-detection.c b/drivers/misc/gpio-detection.c deleted file mode 100644 index 69eda8e5e0ef..000000000000 --- a/drivers/misc/gpio-detection.c +++ /dev/null @@ -1,442 +0,0 @@ -/* - * gpio detection driver - * - * Copyright (C) 2015 Rockchip Electronics Co., Ltd. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define WAKE_LOCK_TIMEOUT_MS (5000) - -struct gpio_data { - struct gpio_detection *parent; - const char *name; - struct device dev; - int notify; - struct gpio_desc *gpio; - int val; - int irq; - struct delayed_work work; - unsigned int debounce_ms; - int wakeup; -}; - -struct gpio_detection { - struct class_attribute cls_attr; - struct device *dev; - int num; - struct gpio_data *data; - struct pinctrl *pinctrl; - struct pinctrl_state *pins_default; - struct notifier_block fb_notifier; - struct wake_lock wake_lock; - int mirror; - int type; - int info; -}; - -static struct class *gpio_detection_class; -static BLOCKING_NOTIFIER_HEAD(gpio_det_notifier_list); -static int system_suspend; - -#if IS_ENABLED(CONFIG_GPIO_DET) - -/* - * gpio_det_notifier_call_chain - notify clients of gpio_det_events - * - */ -int gpio_det_notifier_call_chain(unsigned long val, void *v) -{ - return blocking_notifier_call_chain(&gpio_det_notifier_list, val, v); -} -EXPORT_SYMBOL_GPL(gpio_det_notifier_call_chain); - -/* - * gpio_det_register_notifier - register a client notifier - * @nb: notifier block to callback on events - */ -int gpio_det_register_notifier(struct notifier_block *nb) -{ - int ret = blocking_notifier_chain_register(&gpio_det_notifier_list, nb); - - return ret; -} -EXPORT_SYMBOL(gpio_det_register_notifier); - -/* - * gpio_det_unregister_client - unregister a client notifier - * @nb: notifier block to callback on events - */ -int gpio_det_unregister_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_unregister(&gpio_det_notifier_list, nb); -} -EXPORT_SYMBOL(gpio_det_unregister_notifier); - -#endif - -static void gpio_det_report_event(struct gpio_data *gpiod) -{ - struct gpio_event event; - struct gpio_detection *gpio_det = gpiod->parent; - char *status = NULL; - char *envp[2]; - - event.val = gpiod->val; - event.name = gpiod->name; - status = kasprintf(GFP_KERNEL, "GPIO_NAME=%s GPIO_STATE=%s", - gpiod->name, event.val ? "over" : "on"); - envp[0] = status; - envp[1] = NULL; - wake_lock_timeout(&gpio_det->wake_lock, - msecs_to_jiffies(WAKE_LOCK_TIMEOUT_MS)); - kobject_uevent_env(&gpiod->dev.kobj, KOBJ_CHANGE, envp); - if (gpiod->notify) - gpio_det_notifier_call_chain(GPIO_EVENT, &event); - kfree(status); -} - -static void gpio_det_work_func(struct work_struct *work) -{ - struct gpio_data *gpiod = container_of(work, struct gpio_data, - work.work); - int val = gpiod_get_value(gpiod->gpio); - - if (gpiod->val != val) { - gpiod->val = val; - gpio_det_report_event(gpiod); - if (system_suspend && gpiod->wakeup) { - rk_send_power_key(1); - rk_send_power_key(0); - } - } -} - -static irqreturn_t gpio_det_interrupt(int irq, void *dev_id) -{ - struct gpio_data *gpiod = dev_id; - int val = gpiod_get_raw_value(gpiod->gpio); - unsigned int irqflags = IRQF_ONESHOT; - - if (val) - irqflags |= IRQ_TYPE_EDGE_FALLING; - else - irqflags |= IRQ_TYPE_EDGE_RISING; - irq_set_irq_type(gpiod->irq, irqflags); - - mod_delayed_work(system_wq, &gpiod->work, - msecs_to_jiffies(gpiod->debounce_ms)); - - return IRQ_HANDLED; -} - -static int gpio_det_init_status_check(struct gpio_detection *gpio_det) -{ - struct gpio_data *gpiod; - int i; - - for (i = 0; i < gpio_det->num; i++) { - gpiod = &gpio_det->data[i]; - gpiod->val = gpiod_get_value(gpiod->gpio); - if (gpiod->val) - gpio_det_report_event(gpiod); - } - - return 0; -} - -static int gpio_det_fb_notifier_callback(struct notifier_block *self, - unsigned long event, - void *data) -{ - struct gpio_detection *gpio_det; - struct fb_event *evdata = data; - int fb_blank; - - if (event != FB_EVENT_BLANK && event != FB_EVENT_CONBLANK) - return 0; - - gpio_det = container_of(self, struct gpio_detection, fb_notifier); - fb_blank = *(int *)evdata->data; - if (fb_blank == FB_BLANK_UNBLANK) - system_suspend = 0; - else - system_suspend = 1; - - return 0; -} - -static int gpio_det_fb_notifier_register(struct gpio_detection *gpio) -{ - gpio->fb_notifier.notifier_call = gpio_det_fb_notifier_callback; - - return fb_register_client(&gpio->fb_notifier); -} - -static ssize_t gpio_detection_info_show(struct class *class, - struct class_attribute *attr, - char *buf) -{ - struct gpio_detection *gpio_det; - - gpio_det = container_of(attr, struct gpio_detection, cls_attr); - - return sprintf(buf, "%d\n", gpio_det->info); -} - -static ssize_t status_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct gpio_data *gpiod = container_of(dev, struct gpio_data, dev); - unsigned int val = gpiod_get_value(gpiod->gpio); - - return sprintf(buf, "%d\n", val); -} - -static ssize_t status_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct gpio_data *gpiod; - int val; - int ret; - struct gpio_event event; - - gpiod = container_of(dev, struct gpio_data, dev); - ret = kstrtoint(buf, 0, &val); - if (ret < 0) - return ret; - if (val >= 0) { - event.val = val; - event.name = gpiod->name; - gpio_det_notifier_call_chain(GPIO_EVENT, &event); - } else { - gpiod->notify = 0; - } - - return count; -} - -static DEVICE_ATTR_RW(status); - -static struct attribute *gpio_detection_attrs[] = { - &dev_attr_status.attr, - NULL, -}; -ATTRIBUTE_GROUPS(gpio_detection); - -static int __init gpio_deteciton_class_init(void) -{ - gpio_detection_class = class_create(THIS_MODULE, "gpio-detection"); - if (IS_ERR(gpio_detection_class)) { - pr_err("create gpio_detection class failed (%ld)\n", - PTR_ERR(gpio_detection_class)); - return PTR_ERR(gpio_detection_class); - } - - return 0; -} - -static int gpio_detection_class_register(struct gpio_detection *gpio_det, - struct gpio_data *gpiod) -{ - int ret; - - gpiod->dev.class = gpio_detection_class; - dev_set_name(&gpiod->dev, "%s", gpiod->name); - dev_set_drvdata(&gpiod->dev, gpio_det); - ret = device_register(&gpiod->dev); - ret = sysfs_create_groups(&gpiod->dev.kobj, gpio_detection_groups); - - return ret; -} - -static int gpio_det_parse_dt(struct gpio_detection *gpio_det, - struct platform_device *pdev) -{ - struct gpio_data *data; - struct device *dev = &pdev->dev; - struct device_node *node; - struct gpio_data *gpiod; - struct fwnode_handle *child; - int count = 0; - int i = 0; - int num = 0; - - num = of_get_child_count(gpio_det->dev->of_node); - count = device_get_child_node_count(dev); - if (!count || !num) - return -ENODEV; - data = devm_kzalloc(gpio_det->dev, num * sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - of_property_read_u32(gpio_det->dev->of_node, "rockchip,camcap-type", - &gpio_det->type); - of_property_read_u32(gpio_det->dev->of_node, "rockchip,camcap-mirror", - &gpio_det->mirror); - gpio_det->info = (gpio_det->mirror << 4) | gpio_det->type; - device_for_each_child_node(dev, child) { - node = to_of_node(child); - gpiod = &data[i++]; - gpiod->parent = gpio_det; - gpiod->notify = 1; - gpiod->name = of_get_property(node, "label", NULL); - gpiod->wakeup = !!of_get_property(node, "gpio,wakeup", NULL); - of_property_read_u32(node, "linux,debounce-ms", - &gpiod->debounce_ms); - if (!strcmp(gpiod->name, "car-reverse")) - gpiod->gpio = devm_get_gpiod_from_child(dev, - "car-reverse", child); - else - gpiod->gpio = devm_get_gpiod_from_child(dev, - "car-acc", child); - } - gpio_det->num = num; - gpio_det->data = data; - - return 0; -} - -static int gpio_det_probe(struct platform_device *pdev) -{ - struct gpio_detection *gpio_det; - struct gpio_data *gpiod; - unsigned long irqflags = IRQF_ONESHOT; - int i; - int ret; - - gpio_det = devm_kzalloc(&pdev->dev, sizeof(*gpio_det), GFP_KERNEL); - if (!gpio_det) - return -ENOMEM; - gpio_det->dev = &pdev->dev; - gpio_det->cls_attr.attr.name = "info"; - gpio_det->cls_attr.attr.mode = S_IRUGO; - gpio_det->cls_attr.show = gpio_detection_info_show; - dev_set_name(gpio_det->dev, "gpio_detection"); - if (!pdev->dev.of_node) - return -EINVAL; - gpio_det->pinctrl = devm_pinctrl_get(&pdev->dev); - if (IS_ERR(gpio_det->pinctrl)) { - dev_err(&pdev->dev, "pinctrl get failed\n"); - return PTR_ERR(gpio_det->pinctrl); - } - gpio_det->pins_default = pinctrl_lookup_state(gpio_det->pinctrl, - PINCTRL_STATE_DEFAULT); - if (IS_ERR(gpio_det->pins_default)) - dev_err(gpio_det->dev, "get default pinstate failed\n"); - else - pinctrl_select_state(gpio_det->pinctrl, gpio_det->pins_default); - if (gpio_det_parse_dt(gpio_det, pdev)) - return -ENODEV; - wake_lock_init(&gpio_det->wake_lock, WAKE_LOCK_SUSPEND, - "gpio_detection"); - for (i = 0; i < gpio_det->num; i++) { - gpiod = &gpio_det->data[i]; - gpiod_direction_input(gpiod->gpio); - - gpiod->irq = gpiod_to_irq(gpiod->gpio); - if (gpiod->irq < 0) { - dev_err(gpio_det->dev, "failed to get irq number for GPIO %s\n", - gpiod->name); - continue; - } - - ret = gpio_detection_class_register(gpio_det, gpiod); - if (ret < 0) - return ret; - INIT_DELAYED_WORK(&gpiod->work, gpio_det_work_func); - gpiod->val = gpiod_get_raw_value(gpiod->gpio); - if (gpiod->val) - irqflags |= IRQ_TYPE_EDGE_FALLING; - else - irqflags |= IRQ_TYPE_EDGE_RISING; - ret = devm_request_threaded_irq(gpio_det->dev, gpiod->irq, - NULL, gpio_det_interrupt, - irqflags | IRQF_ONESHOT, - gpiod->name, gpiod); - if (ret < 0) - dev_err(gpio_det->dev, "request irq(%s) failed:%d\n", - gpiod->name, ret); - else - if (gpiod->wakeup) - enable_irq_wake(gpiod->irq); - } - - if (gpio_det->info) { - ret = class_create_file(gpio_detection_class, - &gpio_det->cls_attr); - if (ret) - dev_warn(gpio_det->dev, "create class file failed:%d\n", - ret); - } - - gpio_det_fb_notifier_register(gpio_det); - gpio_det_init_status_check(gpio_det); - - dev_info(gpio_det->dev, "gpio detection driver probe success\n"); - - return 0; -} - -#if defined(CONFIG_OF) -static const struct of_device_id gpio_det_of_match[] = { - { - .compatible = "gpio-detection" - }, - {}, -}; -#endif - -static struct platform_driver gpio_det_driver = { - .driver = { - .name = "gpio-detection", - .of_match_table = of_match_ptr(gpio_det_of_match), - }, - .probe = gpio_det_probe, -}; - -#ifdef CONFIG_VIDEO_REVERSE_IMAGE -int gpio_det_init(void) -#else -static int __init gpio_det_init(void) -#endif -{ - if (!gpio_deteciton_class_init()) - return platform_driver_register(&gpio_det_driver); - else - return -1; -} - -#ifndef CONFIG_VIDEO_REVERSE_IMAGE -fs_initcall_sync(gpio_det_init); -#endif -static void __exit gpio_det_exit(void) -{ - platform_driver_unregister(&gpio_det_driver); -} - -module_exit(gpio_det_exit); - -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:gpio-detection"); -MODULE_AUTHOR("ROCKCHIP"); diff --git a/include/linux/gpio_detection.h b/include/linux/gpio_detection.h deleted file mode 100644 index 57b2ff92bc50..000000000000 --- a/include/linux/gpio_detection.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * include/linux/gpio_detection.h - * - * Platform data structure for GPIO detection driver - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ -#ifndef __GPIO_DETECTION_H -#define __GPIO_DETECTION_H - -#define GPIO_EVENT 1 - -/* - * gpio event - * @val: 0 event active, 1 event over - * @name: event name - */ - -struct gpio_event { - int val; - const char *name; -}; - -#if IS_ENABLED(CONFIG_GPIO_DET) - -int gpio_det_register_notifier(struct notifier_block *nb); -int gpio_det_unregister_notifier(struct notifier_block *nb); -int gpio_det_notifier_call_chain(unsigned long val, void *v); - -#else - -static inline int gpio_det_register_notifier(struct notifier_block *nb) -{ - return -EINVAL; -}; - -static inline int gpio_det_unregister_notifier(struct notifier_block *nb) -{ - return -EINVAL; -}; - -static inline int gpio_det_notifier_call_chain(unsigned long val, void *v) -{ - return -EINVAL; -}; - -#endif - -#endif