diff options
Diffstat (limited to 'drivers/input/keyboard/gpio_keys.c')
| -rw-r--r-- | drivers/input/keyboard/gpio_keys.c | 103 | 
1 files changed, 68 insertions, 35 deletions
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 6a68041c261..b29ca651a39 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -423,10 +423,10 @@ out:  	return IRQ_HANDLED;  } -static int __devinit gpio_keys_setup_key(struct platform_device *pdev, -					 struct input_dev *input, -					 struct gpio_button_data *bdata, -					 const struct gpio_keys_button *button) +static int gpio_keys_setup_key(struct platform_device *pdev, +				struct input_dev *input, +				struct gpio_button_data *bdata, +				const struct gpio_keys_button *button)  {  	const char *desc = button->desc ? button->desc : "gpio_keys";  	struct device *dev = &pdev->dev; @@ -440,21 +440,13 @@ static int __devinit gpio_keys_setup_key(struct platform_device *pdev,  	if (gpio_is_valid(button->gpio)) { -		error = gpio_request(button->gpio, desc); +		error = gpio_request_one(button->gpio, GPIOF_IN, desc);  		if (error < 0) {  			dev_err(dev, "Failed to request GPIO %d, error %d\n",  				button->gpio, error);  			return error;  		} -		error = gpio_direction_input(button->gpio); -		if (error < 0) { -			dev_err(dev, -				"Failed to configure direction for GPIO %d, error %d\n", -				button->gpio, error); -			goto fail; -		} -  		if (button->debounce_interval) {  			error = gpio_set_debounce(button->gpio,  					button->debounce_interval * 1000); @@ -526,12 +518,35 @@ fail:  	return error;  } +static void gpio_keys_report_state(struct gpio_keys_drvdata *ddata) +{ +	struct input_dev *input = ddata->input; +	int i; + +	for (i = 0; i < ddata->pdata->nbuttons; i++) { +		struct gpio_button_data *bdata = &ddata->data[i]; +		if (gpio_is_valid(bdata->button->gpio)) +			gpio_keys_gpio_report_event(bdata); +	} +	input_sync(input); +} +  static int gpio_keys_open(struct input_dev *input)  {  	struct gpio_keys_drvdata *ddata = input_get_drvdata(input);  	const struct gpio_keys_platform_data *pdata = ddata->pdata; +	int error; -	return pdata->enable ? pdata->enable(input->dev.parent) : 0; +	if (pdata->enable) { +		error = pdata->enable(input->dev.parent); +		if (error) +			return error; +	} + +	/* Report current state of buttons that are connected to GPIOs */ +	gpio_keys_report_state(ddata); + +	return 0;  }  static void gpio_keys_close(struct input_dev *input) @@ -551,7 +566,7 @@ static void gpio_keys_close(struct input_dev *input)  /*   * Translate OpenFirmware node properties into platform_data   */ -static struct gpio_keys_platform_data * __devinit +static struct gpio_keys_platform_data *  gpio_keys_get_devtree_pdata(struct device *dev)  {  	struct device_node *node, *pp; @@ -587,6 +602,7 @@ gpio_keys_get_devtree_pdata(struct device *dev)  	i = 0;  	for_each_child_of_node(node, pp) { +		int gpio;  		enum of_gpio_flags flags;  		if (!of_find_property(pp, "gpios", NULL)) { @@ -595,9 +611,19 @@ gpio_keys_get_devtree_pdata(struct device *dev)  			continue;  		} +		gpio = of_get_gpio_flags(pp, 0, &flags); +		if (gpio < 0) { +			error = gpio; +			if (error != -EPROBE_DEFER) +				dev_err(dev, +					"Failed to get gpio flags, error: %d\n", +					error); +			goto err_free_pdata; +		} +  		button = &pdata->buttons[i++]; -		button->gpio = of_get_gpio_flags(pp, 0, &flags); +		button->gpio = gpio;  		button->active_low = flags & OF_GPIO_ACTIVE_LOW;  		if (of_property_read_u32(pp, "linux,code", &button->code)) { @@ -658,7 +684,7 @@ static void gpio_remove_key(struct gpio_button_data *bdata)  		gpio_free(bdata->button->gpio);  } -static int __devinit gpio_keys_probe(struct platform_device *pdev) +static int gpio_keys_probe(struct platform_device *pdev)  {  	struct device *dev = &pdev->dev;  	const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); @@ -731,14 +757,6 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)  		goto fail3;  	} -	/* get current state of buttons that are connected to GPIOs */ -	for (i = 0; i < pdata->nbuttons; i++) { -		struct gpio_button_data *bdata = &ddata->data[i]; -		if (gpio_is_valid(bdata->button->gpio)) -			gpio_keys_gpio_report_event(bdata); -	} -	input_sync(input); -  	device_init_wakeup(&pdev->dev, wakeup);  	return 0; @@ -760,7 +778,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)  	return error;  } -static int __devexit gpio_keys_remove(struct platform_device *pdev) +static int gpio_keys_remove(struct platform_device *pdev)  {  	struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);  	struct input_dev *input = ddata->input; @@ -788,6 +806,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)  static int gpio_keys_suspend(struct device *dev)  {  	struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); +	struct input_dev *input = ddata->input;  	int i;  	if (device_may_wakeup(dev)) { @@ -796,6 +815,11 @@ static int gpio_keys_suspend(struct device *dev)  			if (bdata->button->wakeup)  				enable_irq_wake(bdata->irq);  		} +	} else { +		mutex_lock(&input->mutex); +		if (input->users) +			gpio_keys_close(input); +		mutex_unlock(&input->mutex);  	}  	return 0; @@ -804,18 +828,27 @@ static int gpio_keys_suspend(struct device *dev)  static int gpio_keys_resume(struct device *dev)  {  	struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); +	struct input_dev *input = ddata->input; +	int error = 0;  	int i; -	for (i = 0; i < ddata->pdata->nbuttons; i++) { -		struct gpio_button_data *bdata = &ddata->data[i]; -		if (bdata->button->wakeup && device_may_wakeup(dev)) -			disable_irq_wake(bdata->irq); - -		if (gpio_is_valid(bdata->button->gpio)) -			gpio_keys_gpio_report_event(bdata); +	if (device_may_wakeup(dev)) { +		for (i = 0; i < ddata->pdata->nbuttons; i++) { +			struct gpio_button_data *bdata = &ddata->data[i]; +			if (bdata->button->wakeup) +				disable_irq_wake(bdata->irq); +		} +	} else { +		mutex_lock(&input->mutex); +		if (input->users) +			error = gpio_keys_open(input); +		mutex_unlock(&input->mutex);  	} -	input_sync(ddata->input); +	if (error) +		return error; + +	gpio_keys_report_state(ddata);  	return 0;  }  #endif @@ -824,7 +857,7 @@ static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume);  static struct platform_driver gpio_keys_device_driver = {  	.probe		= gpio_keys_probe, -	.remove		= __devexit_p(gpio_keys_remove), +	.remove		= gpio_keys_remove,  	.driver		= {  		.name	= "gpio-keys",  		.owner	= THIS_MODULE,  |