diff options
Diffstat (limited to 'drivers/input/keyboard/gpio_keys.c')
| -rw-r--r-- | drivers/input/keyboard/gpio_keys.c | 114 | 
1 files changed, 57 insertions, 57 deletions
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index d4dd78a7d56b..883d6aed5b9a 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -35,9 +35,13 @@  struct gpio_button_data {  	const struct gpio_keys_button *button;  	struct input_dev *input; -	struct timer_list timer; -	struct work_struct work; -	unsigned int timer_debounce;	/* in msecs */ + +	struct timer_list release_timer; +	unsigned int release_delay;	/* in msecs, for IRQ-only buttons */ + +	struct delayed_work work; +	unsigned int software_debounce;	/* in msecs, for GPIO-driven buttons */ +  	unsigned int irq;  	spinlock_t lock;  	bool disabled; @@ -116,11 +120,14 @@ static void gpio_keys_disable_button(struct gpio_button_data *bdata)  {  	if (!bdata->disabled) {  		/* -		 * Disable IRQ and possible debouncing timer. +		 * Disable IRQ and associated timer/work structure.  		 */  		disable_irq(bdata->irq); -		if (bdata->timer_debounce) -			del_timer_sync(&bdata->timer); + +		if (gpio_is_valid(bdata->button->gpio)) +			cancel_delayed_work_sync(&bdata->work); +		else +			del_timer_sync(&bdata->release_timer);  		bdata->disabled = true;  	} @@ -343,7 +350,7 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata)  static void gpio_keys_gpio_work_func(struct work_struct *work)  {  	struct gpio_button_data *bdata = -		container_of(work, struct gpio_button_data, work); +		container_of(work, struct gpio_button_data, work.work);  	gpio_keys_gpio_report_event(bdata); @@ -351,13 +358,6 @@ static void gpio_keys_gpio_work_func(struct work_struct *work)  		pm_relax(bdata->input->dev.parent);  } -static void gpio_keys_gpio_timer(unsigned long _data) -{ -	struct gpio_button_data *bdata = (struct gpio_button_data *)_data; - -	schedule_work(&bdata->work); -} -  static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id)  {  	struct gpio_button_data *bdata = dev_id; @@ -366,11 +366,10 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id)  	if (bdata->button->wakeup)  		pm_stay_awake(bdata->input->dev.parent); -	if (bdata->timer_debounce) -		mod_timer(&bdata->timer, -			jiffies + msecs_to_jiffies(bdata->timer_debounce)); -	else -		schedule_work(&bdata->work); + +	mod_delayed_work(system_wq, +			 &bdata->work, +			 msecs_to_jiffies(bdata->software_debounce));  	return IRQ_HANDLED;  } @@ -408,7 +407,7 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)  		input_event(input, EV_KEY, button->code, 1);  		input_sync(input); -		if (!bdata->timer_debounce) { +		if (!bdata->release_delay) {  			input_event(input, EV_KEY, button->code, 0);  			input_sync(input);  			goto out; @@ -417,9 +416,9 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)  		bdata->key_pressed = true;  	} -	if (bdata->timer_debounce) -		mod_timer(&bdata->timer, -			jiffies + msecs_to_jiffies(bdata->timer_debounce)); +	if (bdata->release_delay) +		mod_timer(&bdata->release_timer, +			jiffies + msecs_to_jiffies(bdata->release_delay));  out:  	spin_unlock_irqrestore(&bdata->lock, flags);  	return IRQ_HANDLED; @@ -429,10 +428,10 @@ static void gpio_keys_quiesce_key(void *data)  {  	struct gpio_button_data *bdata = data; -	if (bdata->timer_debounce) -		del_timer_sync(&bdata->timer); - -	cancel_work_sync(&bdata->work); +	if (gpio_is_valid(bdata->button->gpio)) +		cancel_delayed_work_sync(&bdata->work); +	else +		del_timer_sync(&bdata->release_timer);  }  static int gpio_keys_setup_key(struct platform_device *pdev, @@ -466,23 +465,25 @@ static int gpio_keys_setup_key(struct platform_device *pdev,  					button->debounce_interval * 1000);  			/* use timer if gpiolib doesn't provide debounce */  			if (error < 0) -				bdata->timer_debounce = +				bdata->software_debounce =  						button->debounce_interval;  		} -		irq = gpio_to_irq(button->gpio); -		if (irq < 0) { -			error = irq; -			dev_err(dev, -				"Unable to get irq number for GPIO %d, error %d\n", -				button->gpio, error); -			return error; +		if (button->irq) { +			bdata->irq = button->irq; +		} else { +			irq = gpio_to_irq(button->gpio); +			if (irq < 0) { +				error = irq; +				dev_err(dev, +					"Unable to get irq number for GPIO %d, error %d\n", +					button->gpio, error); +				return error; +			} +			bdata->irq = irq;  		} -		bdata->irq = irq; -		INIT_WORK(&bdata->work, gpio_keys_gpio_work_func); -		setup_timer(&bdata->timer, -			    gpio_keys_gpio_timer, (unsigned long)bdata); +		INIT_DELAYED_WORK(&bdata->work, gpio_keys_gpio_work_func);  		isr = gpio_keys_gpio_isr;  		irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; @@ -499,8 +500,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev,  			return -EINVAL;  		} -		bdata->timer_debounce = button->debounce_interval; -		setup_timer(&bdata->timer, +		bdata->release_delay = button->debounce_interval; +		setup_timer(&bdata->release_timer,  			    gpio_keys_irq_timer, (unsigned long)bdata);  		isr = gpio_keys_irq_isr; @@ -510,7 +511,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev,  	input_set_capability(input, button->type ?: EV_KEY, button->code);  	/* -	 * Install custom action to cancel debounce timer and +	 * Install custom action to cancel release timer and  	 * workqueue item.  	 */  	error = devm_add_action(&pdev->dev, gpio_keys_quiesce_key, bdata); @@ -618,33 +619,30 @@ gpio_keys_get_devtree_pdata(struct device *dev)  	i = 0;  	for_each_child_of_node(node, pp) { -		int gpio = -1;  		enum of_gpio_flags flags;  		button = &pdata->buttons[i++]; -		if (!of_find_property(pp, "gpios", NULL)) { -			button->irq = irq_of_parse_and_map(pp, 0); -			if (button->irq == 0) { -				i--; -				pdata->nbuttons--; -				dev_warn(dev, "Found button without gpios or irqs\n"); -				continue; -			} -		} else { -			gpio = of_get_gpio_flags(pp, 0, &flags); -			if (gpio < 0) { -				error = gpio; +		button->gpio = of_get_gpio_flags(pp, 0, &flags); +		if (button->gpio < 0) { +			error = button->gpio; +			if (error != -ENOENT) {  				if (error != -EPROBE_DEFER)  					dev_err(dev,  						"Failed to get gpio flags, error: %d\n",  						error);  				return ERR_PTR(error);  			} +		} else { +			button->active_low = flags & OF_GPIO_ACTIVE_LOW;  		} -		button->gpio = gpio; -		button->active_low = flags & OF_GPIO_ACTIVE_LOW; +		button->irq = irq_of_parse_and_map(pp, 0); + +		if (!gpio_is_valid(button->gpio) && !button->irq) { +			dev_err(dev, "Found button without gpios or irqs\n"); +			return ERR_PTR(-EINVAL); +		}  		if (of_property_read_u32(pp, "linux,code", &button->code)) {  			dev_err(dev, "Button without keycode: 0x%x\n", @@ -659,6 +657,8 @@ gpio_keys_get_devtree_pdata(struct device *dev)  		button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); +		button->can_disable = !!of_get_property(pp, "linux,can-disable", NULL); +  		if (of_property_read_u32(pp, "debounce-interval",  					 &button->debounce_interval))  			button->debounce_interval = 5;  | 
