diff options
author | Sachin Kamat <sachin.kamat@linaro.org> | 2012-11-28 01:34:38 -0500 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-11-28 01:38:37 -0500 |
commit | a57da34795452bbe44b55e2b69c3ab6b117cc4b4 (patch) | |
tree | 049d65cd15dd174103aec81e5fae42c23db0472c /drivers/input | |
parent | 9336648978c2e9de9bf3c026918db386ace19a86 (diff) |
Input: samsung-keypad - switch to using managed resources
devm_* functions are device managed and make error handling and code
simpler. While at it also fix error exit paths.
Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/keyboard/samsung-keypad.c | 103 |
1 files changed, 31 insertions, 72 deletions
diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c index acc161966c3e..22e357b51024 100644 --- a/drivers/input/keyboard/samsung-keypad.c +++ b/drivers/input/keyboard/samsung-keypad.c | |||
@@ -309,7 +309,7 @@ static void samsung_keypad_parse_dt_gpio(struct device *dev, | |||
309 | struct samsung_keypad *keypad) | 309 | struct samsung_keypad *keypad) |
310 | { | 310 | { |
311 | struct device_node *np = dev->of_node; | 311 | struct device_node *np = dev->of_node; |
312 | int gpio, ret, row, col; | 312 | int gpio, error, row, col; |
313 | 313 | ||
314 | for (row = 0; row < keypad->rows; row++) { | 314 | for (row = 0; row < keypad->rows; row++) { |
315 | gpio = of_get_named_gpio(np, "row-gpios", row); | 315 | gpio = of_get_named_gpio(np, "row-gpios", row); |
@@ -320,10 +320,11 @@ static void samsung_keypad_parse_dt_gpio(struct device *dev, | |||
320 | continue; | 320 | continue; |
321 | } | 321 | } |
322 | 322 | ||
323 | ret = gpio_request(gpio, "keypad-row"); | 323 | error = devm_gpio_request(dev, gpio, "keypad-row"); |
324 | if (ret) | 324 | if (error) |
325 | dev_err(dev, "keypad row[%d] gpio request failed\n", | 325 | dev_err(dev, |
326 | row); | 326 | "keypad row[%d] gpio request failed: %d\n", |
327 | row, error); | ||
327 | } | 328 | } |
328 | 329 | ||
329 | for (col = 0; col < keypad->cols; col++) { | 330 | for (col = 0; col < keypad->cols; col++) { |
@@ -335,35 +336,19 @@ static void samsung_keypad_parse_dt_gpio(struct device *dev, | |||
335 | continue; | 336 | continue; |
336 | } | 337 | } |
337 | 338 | ||
338 | ret = gpio_request(gpio, "keypad-col"); | 339 | error = devm_gpio_request(dev, gpio, "keypad-col"); |
339 | if (ret) | 340 | if (error) |
340 | dev_err(dev, "keypad column[%d] gpio request failed\n", | 341 | dev_err(dev, |
341 | col); | 342 | "keypad column[%d] gpio request failed: %d\n", |
343 | col, error); | ||
342 | } | 344 | } |
343 | } | 345 | } |
344 | |||
345 | static void samsung_keypad_dt_gpio_free(struct samsung_keypad *keypad) | ||
346 | { | ||
347 | int cnt; | ||
348 | |||
349 | for (cnt = 0; cnt < keypad->rows; cnt++) | ||
350 | if (gpio_is_valid(keypad->row_gpios[cnt])) | ||
351 | gpio_free(keypad->row_gpios[cnt]); | ||
352 | |||
353 | for (cnt = 0; cnt < keypad->cols; cnt++) | ||
354 | if (gpio_is_valid(keypad->col_gpios[cnt])) | ||
355 | gpio_free(keypad->col_gpios[cnt]); | ||
356 | } | ||
357 | #else | 346 | #else |
358 | static | 347 | static |
359 | struct samsung_keypad_platdata *samsung_keypad_parse_dt(struct device *dev) | 348 | struct samsung_keypad_platdata *samsung_keypad_parse_dt(struct device *dev) |
360 | { | 349 | { |
361 | return NULL; | 350 | return NULL; |
362 | } | 351 | } |
363 | |||
364 | static void samsung_keypad_dt_gpio_free(struct samsung_keypad *keypad) | ||
365 | { | ||
366 | } | ||
367 | #endif | 352 | #endif |
368 | 353 | ||
369 | static int samsung_keypad_probe(struct platform_device *pdev) | 354 | static int samsung_keypad_probe(struct platform_device *pdev) |
@@ -405,36 +390,30 @@ static int samsung_keypad_probe(struct platform_device *pdev) | |||
405 | row_shift = get_count_order(pdata->cols); | 390 | row_shift = get_count_order(pdata->cols); |
406 | keymap_size = (pdata->rows << row_shift) * sizeof(keypad->keycodes[0]); | 391 | keymap_size = (pdata->rows << row_shift) * sizeof(keypad->keycodes[0]); |
407 | 392 | ||
408 | keypad = kzalloc(sizeof(*keypad) + keymap_size, GFP_KERNEL); | 393 | keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad) + keymap_size, |
409 | input_dev = input_allocate_device(); | 394 | GFP_KERNEL); |
410 | if (!keypad || !input_dev) { | 395 | input_dev = devm_input_allocate_device(&pdev->dev); |
411 | error = -ENOMEM; | 396 | if (!keypad || !input_dev) |
412 | goto err_free_mem; | 397 | return -ENOMEM; |
413 | } | ||
414 | 398 | ||
415 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 399 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
416 | if (!res) { | 400 | if (!res) |
417 | error = -ENODEV; | 401 | return -ENODEV; |
418 | goto err_free_mem; | ||
419 | } | ||
420 | 402 | ||
421 | keypad->base = ioremap(res->start, resource_size(res)); | 403 | keypad->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); |
422 | if (!keypad->base) { | 404 | if (!keypad->base) |
423 | error = -EBUSY; | 405 | return -EBUSY; |
424 | goto err_free_mem; | ||
425 | } | ||
426 | 406 | ||
427 | keypad->clk = clk_get(&pdev->dev, "keypad"); | 407 | keypad->clk = devm_clk_get(&pdev->dev, "keypad"); |
428 | if (IS_ERR(keypad->clk)) { | 408 | if (IS_ERR(keypad->clk)) { |
429 | dev_err(&pdev->dev, "failed to get keypad clk\n"); | 409 | dev_err(&pdev->dev, "failed to get keypad clk\n"); |
430 | error = PTR_ERR(keypad->clk); | 410 | return PTR_ERR(keypad->clk); |
431 | goto err_unmap_base; | ||
432 | } | 411 | } |
433 | 412 | ||
434 | error = clk_prepare(keypad->clk); | 413 | error = clk_prepare(keypad->clk); |
435 | if (error) { | 414 | if (error) { |
436 | dev_err(&pdev->dev, "keypad clock prepare failed\n"); | 415 | dev_err(&pdev->dev, "keypad clock prepare failed\n"); |
437 | goto err_put_clk; | 416 | return error; |
438 | } | 417 | } |
439 | 418 | ||
440 | keypad->input_dev = input_dev; | 419 | keypad->input_dev = input_dev; |
@@ -479,14 +458,15 @@ static int samsung_keypad_probe(struct platform_device *pdev) | |||
479 | keypad->irq = platform_get_irq(pdev, 0); | 458 | keypad->irq = platform_get_irq(pdev, 0); |
480 | if (keypad->irq < 0) { | 459 | if (keypad->irq < 0) { |
481 | error = keypad->irq; | 460 | error = keypad->irq; |
482 | goto err_put_clk; | 461 | goto err_unprepare_clk; |
483 | } | 462 | } |
484 | 463 | ||
485 | error = request_threaded_irq(keypad->irq, NULL, samsung_keypad_irq, | 464 | error = devm_request_threaded_irq(&pdev->dev, keypad->irq, NULL, |
486 | IRQF_ONESHOT, dev_name(&pdev->dev), keypad); | 465 | samsung_keypad_irq, IRQF_ONESHOT, |
466 | dev_name(&pdev->dev), keypad); | ||
487 | if (error) { | 467 | if (error) { |
488 | dev_err(&pdev->dev, "failed to register keypad interrupt\n"); | 468 | dev_err(&pdev->dev, "failed to register keypad interrupt\n"); |
489 | goto err_put_clk; | 469 | goto err_unprepare_clk; |
490 | } | 470 | } |
491 | 471 | ||
492 | device_init_wakeup(&pdev->dev, pdata->wakeup); | 472 | device_init_wakeup(&pdev->dev, pdata->wakeup); |
@@ -495,7 +475,7 @@ static int samsung_keypad_probe(struct platform_device *pdev) | |||
495 | 475 | ||
496 | error = input_register_device(keypad->input_dev); | 476 | error = input_register_device(keypad->input_dev); |
497 | if (error) | 477 | if (error) |
498 | goto err_free_irq; | 478 | goto err_disable_runtime_pm; |
499 | 479 | ||
500 | if (pdev->dev.of_node) { | 480 | if (pdev->dev.of_node) { |
501 | devm_kfree(&pdev->dev, (void *)pdata->keymap_data->keymap); | 481 | devm_kfree(&pdev->dev, (void *)pdata->keymap_data->keymap); |
@@ -504,22 +484,12 @@ static int samsung_keypad_probe(struct platform_device *pdev) | |||
504 | } | 484 | } |
505 | return 0; | 485 | return 0; |
506 | 486 | ||
507 | err_free_irq: | 487 | err_disable_runtime_pm: |
508 | free_irq(keypad->irq, keypad); | ||
509 | pm_runtime_disable(&pdev->dev); | 488 | pm_runtime_disable(&pdev->dev); |
510 | device_init_wakeup(&pdev->dev, 0); | 489 | device_init_wakeup(&pdev->dev, 0); |
511 | platform_set_drvdata(pdev, NULL); | 490 | platform_set_drvdata(pdev, NULL); |
512 | err_unprepare_clk: | 491 | err_unprepare_clk: |
513 | clk_unprepare(keypad->clk); | 492 | clk_unprepare(keypad->clk); |
514 | err_put_clk: | ||
515 | clk_put(keypad->clk); | ||
516 | samsung_keypad_dt_gpio_free(keypad); | ||
517 | err_unmap_base: | ||
518 | iounmap(keypad->base); | ||
519 | err_free_mem: | ||
520 | input_free_device(input_dev); | ||
521 | kfree(keypad); | ||
522 | |||
523 | return error; | 493 | return error; |
524 | } | 494 | } |
525 | 495 | ||
@@ -533,18 +503,7 @@ static int samsung_keypad_remove(struct platform_device *pdev) | |||
533 | 503 | ||
534 | input_unregister_device(keypad->input_dev); | 504 | input_unregister_device(keypad->input_dev); |
535 | 505 | ||
536 | /* | ||
537 | * It is safe to free IRQ after unregistering device because | ||
538 | * samsung_keypad_close will shut off interrupts. | ||
539 | */ | ||
540 | free_irq(keypad->irq, keypad); | ||
541 | |||
542 | clk_unprepare(keypad->clk); | 506 | clk_unprepare(keypad->clk); |
543 | clk_put(keypad->clk); | ||
544 | samsung_keypad_dt_gpio_free(keypad); | ||
545 | |||
546 | iounmap(keypad->base); | ||
547 | kfree(keypad); | ||
548 | 507 | ||
549 | return 0; | 508 | return 0; |
550 | } | 509 | } |