Re: [PATCH 2/4] Input: keypad: Add smsc ece1099 keypad driver
From: Poddar, Sourav <hidden>
Date: 2012-08-21 11:30:51
Also in:
linux-arm-kernel, linux-devicetree, linux-omap, lkml
Hi, On Tue, Aug 21, 2012 at 4:15 PM, Felipe Balbi [off-list ref] wrote:
On Tue, Aug 21, 2012 at 04:15:38PM +0530, Sourav Poddar wrote:quoted
From: G, Manjunath Kondaiah <redacted> SMSC ECE1099 is a keyboard scan or GPIO expansion device.The device supports a keypad scan matrix of 23*8.This driver uses this device as a keypad driver. Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com> Cc: Benoit Cousson <redacted> Cc: Felipe Balbi <redacted> Cc: Santosh Shilimkar <redacted> Signed-off-by: G, Manjunath Kondaiah <redacted> Signed-off-by: Sourav Poddar <redacted>looks good. If you just fix my comment on free_irq() below, you can add: Acked-by: Felipe Balbi <redacted>quoted
+static int __devinit +smsc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct smsc *smsc = dev_get_drvdata(pdev->dev.parent); + struct input_dev *input; + struct smsc_keypad *kp; + int ret = 0, error; + int col, i, max_keys, row_shift; + int irq; + int addr_start, addr; + + kp = devm_kzalloc(dev, sizeof(*kp), GFP_KERNEL); + + input = input_allocate_device(); + if (!kp || !input) { + error = -ENOMEM; + goto err1; + } + + error = smsc_keypad_parse_dt(&pdev->dev, kp); + if (error) + return error; + + /* Get the debug Device */ + kp->input = input; + kp->smsc = smsc; + kp->irq = platform_get_irq(pdev, 0); + kp->dev = dev; + + for (col = 0; col < 16; col++) { + kp->last_key_state[col] = 0; + kp->last_key_ms[col] = 0; + } + + /* setup input device */ + __set_bit(EV_KEY, input->evbit); + + /* Enable auto repeat feature of Linux input subsystem */ + if (!(kp->no_autorepeat)) + __set_bit(EV_REP, input->evbit); + + input_set_capability(input, EV_MSC, MSC_SCAN); + input->name = "SMSC Keypad"; + input->phys = "smsc_keypad/input0"; + input->dev.parent = &pdev->dev; + input->id.bustype = BUS_HOST; + input->id.vendor = 0x0001; + input->id.product = 0x0001; + input->id.version = 0x0003; + + error = input_register_device(input); + if (error) { + dev_err(kp->dev, + "Unable to register twl4030 keypad device\n"); + goto err1; + } + + /* Mask all GPIO interrupts (0x37-0x3B) */ + for (addr = 0x37; addr < 0x3B; addr++) + smsc_write(dev, addr, 0); + + /* Set all outputs high (0x05-0x09) */ + for (addr = 0x05; addr < 0x09; addr++) + smsc_write(dev, addr, 0xff); + + /* Clear all GPIO interrupts (0x32-0x36) */ + for (addr = 0x32; addr < 0x36; addr++) + smsc_write(dev, addr, 0xff); + + addr_start = 0x12; + for (i = 0; i <= kp->rows; i++) { + addr = 0x12 + i; + smsc_write(dev, addr, SMSC_KP_KSI); + } + + addr_start = 0x1A; + for (i = 0; i <= kp->cols; i++) { + addr = 0x1A + i; + smsc_write(dev, addr, SMSC_KP_KSO); + } + + addr = SMSC_KP_INT_STAT; + smsc_write(dev, addr, SMSC_KP_SET_HIGH); + + addr = SMSC_WKUP_CTRL; + smsc_write(dev, addr, SMSC_KP_SET_LOW_PWR); + + addr = SMSC_KP_OUT; + smsc_write(dev, addr, SMSC_KSO_ALL_LOW); + + row_shift = get_count_order(kp->cols); + max_keys = kp->rows << row_shift; + + kp->row_shift = row_shift; + kp->keymap = kzalloc(max_keys * sizeof(kp->keymap[0]), + GFP_KERNEL); + if (!kp->keymap) { + dev_err(&pdev->dev, "Not enough memory for keymap\n"); + error = -ENOMEM; + } + + matrix_keypad_build_keymap(NULL, NULL, kp->rows, + kp->cols, kp->keymap, input); + + /* + * This ISR will always execute in kernel thread context because of + * the need to access the SMSC over the I2C bus. + */ + ret = devm_request_threaded_irq(dev, kp->irq, NULL, do_kp_irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, pdev->name, kp); + if (ret) { + dev_dbg(&pdev->dev, "request_irq failed for irq no=%d\n", + irq); + goto err2; + } + + /* Enable smsc keypad interrupts */ + ret = smsc_write(dev, SMSC_KP_INT_MASK, 0xff); + if (ret < 0) + goto err2; + + return 0; + +err2: + input_unregister_device(input); + free_irq(kp->irq, NULL);you're using devm_request_threaded_irq, this is unnecessary
True. Will remove "free_irq" from the code.
quoted
+err1: + input_free_device(input); + return ret; +} + +static int smsc_remove(struct platform_device *pdev) +{ + struct smsc_keypad *kp = platform_get_drvdata(pdev); + free_irq(kp->irq, kp);ditto. -- balbi