mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-09 06:33:34 +00:00
Input: adp5588-keys - switch to using managed resources
This simplifies error handling in probe() and reduces amount of explicit code in remove(). Acked-by: Michael Hennerich <michael.hennerich@analog.com> Link: https://lore.kernel.org/r/20220528045631.289821-3-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
This commit is contained in:
parent
2d1159854f
commit
45608827e6
@ -50,7 +50,6 @@ struct adp5588_kpad {
|
||||
unsigned short gpimapsize;
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
unsigned char gpiomap[ADP5588_MAXGPIO];
|
||||
bool export_gpio;
|
||||
struct gpio_chip gc;
|
||||
struct mutex gpio_lock; /* Protect cached dir, dat_out */
|
||||
u8 dat_out[3];
|
||||
@ -182,6 +181,21 @@ static int adp5588_build_gpiomap(struct adp5588_kpad *kpad,
|
||||
return n_unused;
|
||||
}
|
||||
|
||||
static void adp5588_gpio_do_teardown(void *_kpad)
|
||||
{
|
||||
struct adp5588_kpad *kpad = _kpad;
|
||||
struct device *dev = &kpad->client->dev;
|
||||
const struct adp5588_kpad_platform_data *pdata = dev_get_platdata(dev);
|
||||
const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data;
|
||||
int error;
|
||||
|
||||
error = gpio_data->teardown(kpad->client,
|
||||
kpad->gc.base, kpad->gc.ngpio,
|
||||
gpio_data->context);
|
||||
if (error)
|
||||
dev_warn(&kpad->client->dev, "teardown failed %d\n", error);
|
||||
}
|
||||
|
||||
static int adp5588_gpio_add(struct adp5588_kpad *kpad)
|
||||
{
|
||||
struct device *dev = &kpad->client->dev;
|
||||
@ -198,8 +212,6 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad)
|
||||
return 0;
|
||||
}
|
||||
|
||||
kpad->export_gpio = true;
|
||||
|
||||
kpad->gc.direction_input = adp5588_gpio_direction_input;
|
||||
kpad->gc.direction_output = adp5588_gpio_direction_output;
|
||||
kpad->gc.get = adp5588_gpio_get_value;
|
||||
@ -213,9 +225,9 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad)
|
||||
|
||||
mutex_init(&kpad->gpio_lock);
|
||||
|
||||
error = gpiochip_add_data(&kpad->gc, kpad);
|
||||
error = devm_gpiochip_add_data(dev, &kpad->gc, kpad);
|
||||
if (error) {
|
||||
dev_err(dev, "gpiochip_add failed, err: %d\n", error);
|
||||
dev_err(dev, "gpiochip_add failed: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -230,41 +242,24 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad)
|
||||
kpad->gc.base, kpad->gc.ngpio,
|
||||
gpio_data->context);
|
||||
if (error)
|
||||
dev_warn(dev, "setup failed, %d\n", error);
|
||||
dev_warn(dev, "setup failed: %d\n", error);
|
||||
}
|
||||
|
||||
if (gpio_data->teardown) {
|
||||
error = devm_add_action(dev, adp5588_gpio_do_teardown, kpad);
|
||||
if (error)
|
||||
dev_warn(dev, "failed to schedule teardown: %d\n",
|
||||
error);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void adp5588_gpio_remove(struct adp5588_kpad *kpad)
|
||||
{
|
||||
struct device *dev = &kpad->client->dev;
|
||||
const struct adp5588_kpad_platform_data *pdata = dev_get_platdata(dev);
|
||||
const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data;
|
||||
int error;
|
||||
|
||||
if (!kpad->export_gpio)
|
||||
return;
|
||||
|
||||
if (gpio_data->teardown) {
|
||||
error = gpio_data->teardown(kpad->client,
|
||||
kpad->gc.base, kpad->gc.ngpio,
|
||||
gpio_data->context);
|
||||
if (error)
|
||||
dev_warn(dev, "teardown failed %d\n", error);
|
||||
}
|
||||
|
||||
gpiochip_remove(&kpad->gc);
|
||||
}
|
||||
#else
|
||||
static inline int adp5588_gpio_add(struct adp5588_kpad *kpad)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void adp5588_gpio_remove(struct adp5588_kpad *kpad)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static void adp5588_report_events(struct adp5588_kpad *kpad, int ev_cnt)
|
||||
@ -510,21 +505,20 @@ static int adp5588_probe(struct i2c_client *client,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
kpad = kzalloc(sizeof(*kpad), GFP_KERNEL);
|
||||
input = input_allocate_device();
|
||||
if (!kpad || !input) {
|
||||
error = -ENOMEM;
|
||||
goto err_free_mem;
|
||||
}
|
||||
kpad = devm_kzalloc(&client->dev, sizeof(*kpad), GFP_KERNEL);
|
||||
if (!kpad)
|
||||
return -ENOMEM;
|
||||
|
||||
input = devm_input_allocate_device(&client->dev);
|
||||
if (!input)
|
||||
return -ENOMEM;
|
||||
|
||||
kpad->client = client;
|
||||
kpad->input = input;
|
||||
|
||||
ret = adp5588_read(client, DEV_ID);
|
||||
if (ret < 0) {
|
||||
error = ret;
|
||||
goto err_free_mem;
|
||||
}
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
revid = (u8) ret & ADP5588_DEVICE_ID_MASK;
|
||||
if (WA_DELAYED_READOUT_REVID(revid))
|
||||
@ -532,7 +526,6 @@ static int adp5588_probe(struct i2c_client *client,
|
||||
|
||||
input->name = client->name;
|
||||
input->phys = "adp5588-keys/input0";
|
||||
input->dev.parent = &client->dev;
|
||||
|
||||
input_set_drvdata(input, kpad);
|
||||
|
||||
@ -569,58 +562,43 @@ static int adp5588_probe(struct i2c_client *client,
|
||||
|
||||
error = input_register_device(input);
|
||||
if (error) {
|
||||
dev_err(&client->dev, "unable to register input device\n");
|
||||
goto err_free_mem;
|
||||
dev_err(&client->dev, "unable to register input device: %d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = request_threaded_irq(client->irq,
|
||||
adp5588_hard_irq, adp5588_thread_irq,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
client->dev.driver->name, kpad);
|
||||
error = devm_request_threaded_irq(&client->dev, client->irq,
|
||||
adp5588_hard_irq, adp5588_thread_irq,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
client->dev.driver->name, kpad);
|
||||
if (error) {
|
||||
dev_err(&client->dev, "irq %d busy?\n", client->irq);
|
||||
goto err_unreg_dev;
|
||||
dev_err(&client->dev, "failed to request irq %d: %d\n",
|
||||
client->irq, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = adp5588_setup(client);
|
||||
if (error)
|
||||
goto err_free_irq;
|
||||
return error;
|
||||
|
||||
if (kpad->gpimapsize)
|
||||
adp5588_report_switch_state(kpad);
|
||||
|
||||
error = adp5588_gpio_add(kpad);
|
||||
if (error)
|
||||
goto err_free_irq;
|
||||
return error;
|
||||
|
||||
device_init_wakeup(&client->dev, 1);
|
||||
i2c_set_clientdata(client, kpad);
|
||||
|
||||
dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq);
|
||||
return 0;
|
||||
|
||||
err_free_irq:
|
||||
free_irq(client->irq, kpad);
|
||||
err_unreg_dev:
|
||||
input_unregister_device(input);
|
||||
input = NULL;
|
||||
err_free_mem:
|
||||
input_free_device(input);
|
||||
kfree(kpad);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int adp5588_remove(struct i2c_client *client)
|
||||
{
|
||||
struct adp5588_kpad *kpad = i2c_get_clientdata(client);
|
||||
|
||||
adp5588_write(client, CFG, 0);
|
||||
free_irq(client->irq, kpad);
|
||||
input_unregister_device(kpad->input);
|
||||
adp5588_gpio_remove(kpad);
|
||||
kfree(kpad);
|
||||
|
||||
/* all resources will be freed by devm */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user