Skip to content

Commit

Permalink
Input: adp5588-keys - switch to using managed resources
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Dmitry Torokhov committed May 31, 2022
1 parent 2d11598 commit 4560882
Showing 1 changed file with 45 additions and 67 deletions.
112 changes: 45 additions & 67 deletions drivers/input/keyboard/adp5588-keys.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
}

Expand All @@ -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);
}

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);
error = devm_add_action(dev, adp5588_gpio_do_teardown, kpad);
if (error)
dev_warn(dev, "teardown failed %d\n", error);
dev_warn(dev, "failed to schedule teardown: %d\n",
error);
}

gpiochip_remove(&kpad->gc);
return 0;
}

#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)
Expand Down Expand Up @@ -510,29 +505,27 @@ 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))
kpad->delay = msecs_to_jiffies(WA_DELAYED_READOUT_TIME);

input->name = client->name;
input->phys = "adp5588-keys/input0";
input->dev.parent = &client->dev;

input_set_drvdata(input, kpad);

Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit 4560882

Please sign in to comment.