diff options
Diffstat (limited to 'drivers/input/keyboard/spear-keyboard.c')
-rw-r--r-- | drivers/input/keyboard/spear-keyboard.c | 98 |
1 files changed, 41 insertions, 57 deletions
diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c index c7ca97f44bfb..695d237417d6 100644 --- a/drivers/input/keyboard/spear-keyboard.c +++ b/drivers/input/keyboard/spear-keyboard.c @@ -55,15 +55,15 @@ struct spear_kbd { struct input_dev *input; - struct resource *res; void __iomem *io_base; struct clk *clk; unsigned int irq; unsigned int mode; + unsigned int suspended_rate; unsigned short last_key; unsigned short keycodes[NUM_ROWS * NUM_COLS]; bool rep; - unsigned int suspended_rate; + bool irq_wake_enabled; u32 mode_ctl_reg; }; @@ -146,7 +146,7 @@ static void spear_kbd_close(struct input_dev *dev) } #ifdef CONFIG_OF -static int __devinit spear_kbd_parse_dt(struct platform_device *pdev, +static int spear_kbd_parse_dt(struct platform_device *pdev, struct spear_kbd *kbd) { struct device_node *np = pdev->dev.of_node; @@ -181,7 +181,7 @@ static inline int spear_kbd_parse_dt(struct platform_device *pdev, } #endif -static int __devinit spear_kbd_probe(struct platform_device *pdev) +static int spear_kbd_probe(struct platform_device *pdev) { struct kbd_platform_data *pdata = dev_get_platdata(&pdev->dev); const struct matrix_keymap_data *keymap = pdata ? pdata->keymap : NULL; @@ -203,12 +203,16 @@ static int __devinit spear_kbd_probe(struct platform_device *pdev) return irq; } - kbd = kzalloc(sizeof(*kbd), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!kbd || !input_dev) { - dev_err(&pdev->dev, "out of memory\n"); - error = -ENOMEM; - goto err_free_mem; + kbd = devm_kzalloc(&pdev->dev, sizeof(*kbd), GFP_KERNEL); + if (!kbd) { + dev_err(&pdev->dev, "not enough memory for driver data\n"); + return -ENOMEM; + } + + input_dev = devm_input_allocate_device(&pdev->dev); + if (!input_dev) { + dev_err(&pdev->dev, "unable to allocate input device\n"); + return -ENOMEM; } kbd->input = input_dev; @@ -217,37 +221,25 @@ static int __devinit spear_kbd_probe(struct platform_device *pdev) if (!pdata) { error = spear_kbd_parse_dt(pdev, kbd); if (error) - goto err_free_mem; + return error; } else { kbd->mode = pdata->mode; kbd->rep = pdata->rep; kbd->suspended_rate = pdata->suspended_rate; } - kbd->res = request_mem_region(res->start, resource_size(res), - pdev->name); - if (!kbd->res) { - dev_err(&pdev->dev, "keyboard region already claimed\n"); - error = -EBUSY; - goto err_free_mem; - } - - kbd->io_base = ioremap(res->start, resource_size(res)); + kbd->io_base = devm_request_and_ioremap(&pdev->dev, res); if (!kbd->io_base) { - dev_err(&pdev->dev, "ioremap failed for kbd_region\n"); - error = -ENOMEM; - goto err_release_mem_region; + dev_err(&pdev->dev, "request-ioremap failed for kbd_region\n"); + return -ENOMEM; } - kbd->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(kbd->clk)) { - error = PTR_ERR(kbd->clk); - goto err_iounmap; - } + kbd->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(kbd->clk)) + return PTR_ERR(kbd->clk); input_dev->name = "Spear Keyboard"; input_dev->phys = "keyboard/input0"; - input_dev->dev.parent = &pdev->dev; input_dev->id.bustype = BUS_HOST; input_dev->id.vendor = 0x0001; input_dev->id.product = 0x0001; @@ -259,7 +251,7 @@ static int __devinit spear_kbd_probe(struct platform_device *pdev) kbd->keycodes, input_dev); if (error) { dev_err(&pdev->dev, "Failed to build keymap\n"); - goto err_put_clk; + return error; } if (kbd->rep) @@ -268,48 +260,36 @@ static int __devinit spear_kbd_probe(struct platform_device *pdev) input_set_drvdata(input_dev, kbd); - error = request_irq(irq, spear_kbd_interrupt, 0, "keyboard", kbd); + error = devm_request_irq(&pdev->dev, irq, spear_kbd_interrupt, 0, + "keyboard", kbd); if (error) { - dev_err(&pdev->dev, "request_irq fail\n"); - goto err_put_clk; + dev_err(&pdev->dev, "request_irq failed\n"); + return error; } + error = clk_prepare(kbd->clk); + if (error) + return error; + error = input_register_device(input_dev); if (error) { dev_err(&pdev->dev, "Unable to register keyboard device\n"); - goto err_free_irq; + clk_unprepare(kbd->clk); + return error; } device_init_wakeup(&pdev->dev, 1); platform_set_drvdata(pdev, kbd); return 0; - -err_free_irq: - free_irq(kbd->irq, kbd); -err_put_clk: - clk_put(kbd->clk); -err_iounmap: - iounmap(kbd->io_base); -err_release_mem_region: - release_mem_region(res->start, resource_size(res)); -err_free_mem: - input_free_device(input_dev); - kfree(kbd); - - return error; } -static int __devexit spear_kbd_remove(struct platform_device *pdev) +static int spear_kbd_remove(struct platform_device *pdev) { struct spear_kbd *kbd = platform_get_drvdata(pdev); - free_irq(kbd->irq, kbd); input_unregister_device(kbd->input); - clk_put(kbd->clk); - iounmap(kbd->io_base); - release_mem_region(kbd->res->start, resource_size(kbd->res)); - kfree(kbd); + clk_unprepare(kbd->clk); device_init_wakeup(&pdev->dev, 0); platform_set_drvdata(pdev, NULL); @@ -333,7 +313,8 @@ static int spear_kbd_suspend(struct device *dev) mode_ctl_reg = readl_relaxed(kbd->io_base + MODE_CTL_REG); if (device_may_wakeup(&pdev->dev)) { - enable_irq_wake(kbd->irq); + if (!enable_irq_wake(kbd->irq)) + kbd->irq_wake_enabled = true; /* * reprogram the keyboard operating frequency as on some @@ -379,7 +360,10 @@ static int spear_kbd_resume(struct device *dev) mutex_lock(&input_dev->mutex); if (device_may_wakeup(&pdev->dev)) { - disable_irq_wake(kbd->irq); + if (kbd->irq_wake_enabled) { + kbd->irq_wake_enabled = false; + disable_irq_wake(kbd->irq); + } } else { if (input_dev->users) clk_enable(kbd->clk); @@ -407,7 +391,7 @@ MODULE_DEVICE_TABLE(of, spear_kbd_id_table); static struct platform_driver spear_kbd_driver = { .probe = spear_kbd_probe, - .remove = __devexit_p(spear_kbd_remove), + .remove = spear_kbd_remove, .driver = { .name = "keyboard", .owner = THIS_MODULE, |