From patchwork Tue Jul 10 06:13:26 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 1176021 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id 2CF7540B37 for ; Tue, 10 Jul 2012 06:19:23 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1SoThd-0006Y1-Pe; Tue, 10 Jul 2012 06:13:42 +0000 Received: from mail-pb0-f49.google.com ([209.85.160.49]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1SoThV-0006Ws-RA for linux-arm-kernel@lists.infradead.org; Tue, 10 Jul 2012 06:13:35 +0000 Received: by pbbrq13 with SMTP id rq13so23165082pbb.36 for ; Mon, 09 Jul 2012 23:13:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=date:from:to:cc:subject:message-id:references:mime-version :content-type:content-disposition:in-reply-to:user-agent; bh=BZKPB2m1s4ab6qAnO2spVEmyT91FFv524FcYKo5DA94=; b=ekAGBNh0Iu0NIlF8pfyiRVqMP/pZjIOISeEo9SBhzrhbtQGPOjh3ncV961c7hz1HwE RkDPA3c9wZy4KOanqWBB8MwaaJ1vUQvyRfv7IFBAs8lsPAJ35L9JjzaWZfL97Hm9Zmgv ymybGiPcaixxsNQjiigdjB66H24CCABKTT3wXFroVk05dxz1oSAx7z3EHW0O9rmEWuOS 26wtoTrtIEj8VvCbQagPNYN69V5Hzozdqz/IBcDZYB8u/BoS8C4oJlI7ZOvhQvg6iqsF 50irYRmgHo7yfq8x5+weNq9qukbMLrBTxUNn0YpJCfGns5yqm3cDVR6LzJfioyDqs9m0 owDA== Received: by 10.68.135.201 with SMTP id pu9mr66085432pbb.146.1341900811777; Mon, 09 Jul 2012 23:13:31 -0700 (PDT) Received: from mailhub.coreip.homeip.net (c-67-188-112-76.hsd1.ca.comcast.net. [67.188.112.76]) by mx.google.com with ESMTPS id pi7sm29214482pbb.56.2012.07.09.23.13.29 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 09 Jul 2012 23:13:30 -0700 (PDT) Date: Mon, 9 Jul 2012 23:13:26 -0700 From: Dmitry Torokhov To: Sourav Poddar Subject: Re: [RESEND/PATCHv5 1/2] drivers: input: keypad: Add device tree support Message-ID: <20120710061326.GA29257@core.coreip.homeip.net> References: <1339152780-25301-1-git-send-email-sourav.poddar@ti.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <1339152780-25301-1-git-send-email-sourav.poddar@ti.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-Spam-Note: CRM114 invocation failed X-Spam-Score: -2.7 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [209.85.160.49 listed in list.dnswl.org] 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (dmitry.torokhov[at]gmail.com) -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature Cc: Benoit Cousson , devicetree-discuss@lists.ozlabs.org, linux-kernel@vger.kernel.org, Rob Herring , Grant Likely , Randy Dunlap , Felipe Balbi , linux-input@vger.kernel.org, Andrew Morton , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Hi Sourav, On Fri, Jun 08, 2012 at 04:22:59PM +0530, Sourav Poddar wrote: > Update the Documentation with omap4 keypad device tree > binding information. > Add device tree support for omap4 keypad driver. > > Tested on omap4430 sdp. > Sorry for the delay, I have a few comments: > > /* platform data */ > pdata = pdev->dev.platform_data; > - if (!pdata) { > + if (np) { > + of_property_read_u32(np, "keypad,num-rows", &num_rows); > + of_property_read_u32(np, "keypad,num-columns", &num_cols); > + if (!num_rows || !num_cols) { > + dev_err(&pdev->dev, "number of keypad rows/columns not specified\n"); > + return -EINVAL; > + } > + } else if (pdata) { > + num_rows = pdata->rows; > + num_cols = pdata->cols; > + } else { > dev_err(&pdev->dev, "no platform data defined\n"); > return -EINVAL; > } > I believe drivers should use platform data if it is supplied and use DT data if platform data is omitted. This way one can override firmware data if needed. Does the patch below (if applied on top of your) work for you? Thanks. Acked-by: Sourav Poddar diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c index d5a2d1a..033168e 100644 --- a/drivers/input/keyboard/omap4-keypad.c +++ b/drivers/input/keyboard/omap4-keypad.c @@ -76,7 +76,6 @@ enum { struct omap4_keypad { struct input_dev *input; - struct matrix_keymap_data *keymap_data; void __iomem *base; unsigned int irq; @@ -88,7 +87,7 @@ struct omap4_keypad { unsigned int row_shift; bool no_autorepeat; unsigned char key_state[8]; - unsigned short keymap[]; + unsigned short *keymap; }; static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset) @@ -211,74 +210,52 @@ static void omap4_keypad_close(struct input_dev *input) pm_runtime_put_sync(input->dev.parent); } -static struct omap4_keypad *omap_keypad_parse_dt(struct device *dev, - uint32_t rows, uint32_t cols, - struct input_dev *input_dev) +#ifdef CONFIG_OF +static int __devinit omap4_keypad_parse_dt(struct device *dev, + struct omap4_keypad *keypad_data) { struct device_node *np = dev->of_node; - struct platform_device *pdev = to_platform_device(dev); - struct omap4_keypad *keypad_data = platform_get_drvdata(pdev); int error; - error = matrix_keypad_build_keymap(NULL, "linux,keymap", - rows, cols, keypad_data->keymap, input_dev); - if (error) { - dev_err(&pdev->dev, "failed to build keymap\n"); - input_free_device(input_dev); + if (!np) { + dev_err(dev, "missing DT data"); + return -EINVAL; + } + + of_property_read_u32(np, "keypad,num-rows", &keypad_data->rows); + of_property_read_u32(np, "keypad,num-columns", &keypad_data->cols); + if (!keypad_data->rows || !keypad_data->cols) { + dev_err(dev, "number of keypad rows/columns not specified\n"); + return -EINVAL; } if (of_get_property(np, "linux,input-no-autorepeat", NULL)) keypad_data->no_autorepeat = true; - return keypad_data; + return 0; +} +#else +static inline int omap4_keypad_parse_dt(struct device *dev, + struct omap4_keypad *keypad_data) +{ + return -ENOSYS; } +#endif static int __devinit omap4_keypad_probe(struct platform_device *pdev) { - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - const struct omap4_keypad_platform_data *pdata; + const struct omap4_keypad_platform_data *pdata = + dev_get_platdata(&pdev->dev); + const struct matrix_keymap_data *keymap_data = + pdata ? pdata->keymap_data : NULL; struct omap4_keypad *keypad_data; struct input_dev *input_dev; struct resource *res; - resource_size_t size; - unsigned int row_shift = 0, max_keys = 0; - uint32_t num_rows = 0, num_cols = 0; + unsigned int max_keys; int rev; int irq; int error; - /* platform data */ - pdata = pdev->dev.platform_data; - if (np) { - of_property_read_u32(np, "keypad,num-rows", &num_rows); - of_property_read_u32(np, "keypad,num-columns", &num_cols); - if (!num_rows || !num_cols) { - dev_err(&pdev->dev, "number of keypad rows/columns not specified\n"); - return -EINVAL; - } - } else if (pdata) { - num_rows = pdata->rows; - num_cols = pdata->cols; - } else { - dev_err(&pdev->dev, "no platform data defined\n"); - return -EINVAL; - } - - row_shift = get_count_order(num_cols); - max_keys = num_rows << row_shift; - - keypad_data = devm_kzalloc(dev, sizeof(struct omap4_keypad) + - max_keys * sizeof(keypad_data->keymap[0]), - GFP_KERNEL); - - if (!keypad_data) { - dev_err(&pdev->dev, "keypad_data memory allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(pdev, keypad_data); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "no base address specified\n"); @@ -291,9 +268,24 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev) return -EINVAL; } - size = resource_size(res); + keypad_data = kzalloc(sizeof(struct omap4_keypad), GFP_KERNEL); + if (!keypad_data) { + dev_err(&pdev->dev, "keypad_data memory allocation failed\n"); + return -ENOMEM; + } + + keypad_data->irq = irq; + + if (pdata) { + keypad_data->rows = pdata->rows; + keypad_data->cols = pdata->cols; + } else { + error = omap4_keypad_parse_dt(&pdev->dev, keypad_data); + if (error) + return error; + } - res = request_mem_region(res->start, size, pdev->name); + res = request_mem_region(res->start, resource_size(res), pdev->name); if (!res) { dev_err(&pdev->dev, "can't request mem region\n"); error = -EBUSY; @@ -307,15 +299,11 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev) goto err_release_mem; } - keypad_data->rows = num_rows; - keypad_data->cols = num_cols; - keypad_data->irq = irq; - keypad_data->row_shift = row_shift; /* - * Enable clocks for the keypad module so that we can read - * revision register. - */ + * Enable clocks for the keypad module so that we can read + * revision register. + */ pm_runtime_enable(&pdev->dev); error = pm_runtime_get_sync(&pdev->dev); if (error) { @@ -358,29 +346,30 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev) input_dev->open = omap4_keypad_open; input_dev->close = omap4_keypad_close; - if (np) { - keypad_data = omap_keypad_parse_dt(&pdev->dev, - keypad_data->rows, keypad_data->cols, - input_dev); - } else { - keypad_data->keymap_data = - (struct matrix_keymap_data *)pdata->keymap_data; - error = matrix_keypad_build_keymap(keypad_data->keymap_data, - NULL, keypad_data->rows, keypad_data->cols, - keypad_data->keymap, input_dev); - if (error) { - dev_err(&pdev->dev, "failed to build keymap\n"); - goto err_free_input; - } - } - + input_set_capability(input_dev, EV_MSC, MSC_SCAN); if (!keypad_data->no_autorepeat) __set_bit(EV_REP, input_dev->evbit); - input_set_capability(input_dev, EV_MSC, MSC_SCAN); - input_set_drvdata(input_dev, keypad_data); + keypad_data->row_shift = get_count_order(keypad_data->cols); + max_keys = keypad_data->rows << keypad_data->row_shift; + keypad_data->keymap = kzalloc(max_keys * sizeof(keypad_data->keymap[0]), + GFP_KERNEL); + if (!keypad_data->keymap) { + dev_err(&pdev->dev, "Not enough memory for keymap\n"); + error = -ENOMEM; + goto err_free_input; + } + + error = matrix_keypad_build_keymap(keymap_data, NULL, + keypad_data->rows, keypad_data->cols, + keypad_data->keymap, input_dev); + if (error) { + dev_err(&pdev->dev, "failed to build keymap\n"); + goto err_free_keymap; + } + error = request_irq(keypad_data->irq, omap4_keypad_interrupt, IRQF_TRIGGER_RISING, "omap4-keypad", keypad_data); @@ -397,11 +386,14 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev) goto err_pm_disable; } + platform_set_drvdata(pdev, keypad_data); return 0; err_pm_disable: pm_runtime_disable(&pdev->dev); free_irq(keypad_data->irq, keypad_data); +err_free_keymap: + kfree(keypad_data->keymap); err_free_input: input_free_device(input_dev); err_pm_put_sync: @@ -409,7 +401,7 @@ err_pm_put_sync: err_unmap: iounmap(keypad_data->base); err_release_mem: - release_mem_region(res->start, size); + release_mem_region(res->start, resource_size(res)); err_free_keypad: kfree(keypad_data); return error; @@ -431,17 +423,21 @@ static int __devexit omap4_keypad_remove(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(res->start, resource_size(res)); + kfree(keypad_data->keymap); kfree(keypad_data); + platform_set_drvdata(pdev, NULL); return 0; } +#ifdef CONFIG_OF static const struct of_device_id omap_keypad_dt_match[] = { { .compatible = "ti,omap4-keypad" }, {}, }; MODULE_DEVICE_TABLE(of, omap_keypad_dt_match); +#endif static struct platform_driver omap4_keypad_driver = { .probe = omap4_keypad_probe,