RE: [PATCH v3] input: tegra-kbc - Add tegra keyboard driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Thanks for the review.

A quick response regarding the following comment.

> 
> > +
> > +#include <linux/module.h>
> > +#include <linux/input.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/delay.h>
> > +#include <linux/io.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/clk.h>
> > +#include <linux/slab.h>
> > +#include <mach/clk.h>
> 
> You may not need this.
>

The mach/clk.h file contains declarations for tegra_periph_reset_assert and tegra_periph_reset_deassert which are needed.

Regards
Rakesh

> -----Original Message-----
> From: Trilok Soni [mailto:tsoni@xxxxxxxxxxxxxx]
> Sent: Monday, January 10, 2011 12:54 PM
> To: Rakesh Iyer
> Cc: jj@xxxxxxxxxxxxx; shubhrajyoti@xxxxxx; ccross@xxxxxxxxxxx; konkers@xxxxxxxxxxx;
> olof@xxxxxxxxx; Andrew Chew; linux-tegra@xxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx;
> linux-input@xxxxxxxxxxxxxxx
> Subject: Re: [PATCH v3] input: tegra-kbc - Add tegra keyboard driver
> 
> Hi Rakesh,
> 
> On 1/7/2011 11:15 PM, riyer@xxxxxxxxxx wrote:
> > From: Rakesh Iyer <riyer@xxxxxxxxxx>
> >
> > This patch adds support for the internal matrix keyboard controller for
> > Nvidia Tegra platforms.
> >
> > Signed-off-by: Rakesh Iyer <riyer@xxxxxxxxxx>
> > ---
> > Removed NULL check before input_free_device as suggested by Jesper Juhl.
> 
> Sorry for the delay. Few comments.
> 
> > +
> > +#include <linux/module.h>
> > +#include <linux/input.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/delay.h>
> > +#include <linux/io.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/clk.h>
> > +#include <linux/slab.h>
> > +#include <mach/clk.h>
> 
> You may not need this.
> 
> >
> > +
> > +static void tegra_kbc_keypress_timer(unsigned long data)
> > +{
> > +	struct tegra_kbc *kbc = (struct tegra_kbc *)data;
> > +	unsigned long flags;
> > +	u32 val;
> > +	int i;
> > +
> 
> ...
> 
> > +	}
> > +	return;
> 
> No need.
> 
> > +}
> > +
> > +
> > +
> > +
> > +static int tegra_kbc_open(struct input_dev *dev)
> > +{
> > +	struct tegra_kbc *kbc = input_get_drvdata(dev);
> > +	unsigned long flags;
> > +	unsigned int debounce_cnt;
> > +	u32 val = 0;
> > +
> > +	clk_enable(kbc->clk);
> > +
> > +	/* Reset the KBC controller to clear all previous status.*/
> > +	tegra_periph_reset_assert(kbc->clk);
> > +	udelay(100);
> > +	tegra_periph_reset_deassert(kbc->clk);
> > +	udelay(100);
> > +
> > +	tegra_kbc_config_pins(kbc);
> > +	tegra_kbc_setup_wakekeys(kbc, false);
> > +
> > +	writel(kbc->pdata->repeat_cnt, kbc->mmio + KBC_RPT_DLY_0);
> > +
> > +	debounce_cnt = min_t(unsigned int, kbc->pdata->debounce_cnt, 0x3fful);
> > +	val = debounce_cnt << 4;
> > +	val |= 1<<14; /* fifo interrupt threshold = 1 entry */
> > +	val |= 1<<3;  /* interrupt on FIFO threshold reached */
> 
> As mentioned below, try to get driver out of these magic nos.
> 
> > +	val |= 1;     /* enable */
> > +	writel(val, kbc->mmio + KBC_CONTROL_0);
> > +
> > +	/* Compute the delay(ns) from interrupt mode to continuous polling mode
> > +	 * so the timer routine is scheduled appropriately. */
> > +	val = readl(kbc->mmio + KBC_INIT_DLY_0);
> > +	kbc->cp_dly_jiffies = usecs_to_jiffies((val & 0xfffff) * 32);
> > +
> > +	/* atomically clear out any remaining entries in the key FIFO
> > +	 * and enable keyboard interrupts */
> > +	spin_lock_irqsave(&kbc->lock, flags);
> > +	while (1) {
> > +		val = readl(kbc->mmio + KBC_INT_0);
> > +		val >>= 4;
> > +		if (val) {
> > +			val = readl(kbc->mmio + KBC_KP_ENT0_0);
> > +			val = readl(kbc->mmio + KBC_KP_ENT1_0);
> > +		} else {
> > +			break;
> > +		}
> > +	}
> > +	writel(0x7, kbc->mmio + KBC_INT_0);
> > +	spin_unlock_irqrestore(&kbc->lock, flags);
> > +
> > +	return 0;
> > +}
> > +
> > +
> 
> > +
> > +static irqreturn_t tegra_kbc_isr(int irq, void *args)
> > +{
> > +	struct tegra_kbc *kbc = args;
> > +	u32 val, ctl;
> > +
> > +	/* until all keys are released, defer further processing to
> > +	 * the polling loop in tegra_kbc_keypress_timer */
> > +	ctl = readl(kbc->mmio + KBC_CONTROL_0);
> > +	ctl &= ~(1<<3);
> 
> No magic nos. please. Add relevant #defines for it.
> 
> > +	writel(ctl, kbc->mmio + KBC_CONTROL_0);
> > +
> > +	/* quickly bail out & reenable interrupts if the interrupt source
> > +	 * wasn't fifo count threshold */
> 
> "wasn't equal to fifo count threshold" ?
> 
> > +	val = readl(kbc->mmio + KBC_INT_0);
> > +	writel(val, kbc->mmio + KBC_INT_0);
> > +
> > +	if (!(val & (1<<2))) {
> > +		ctl |= 1<<3;
> 
> As mentioned above, no magic nos. please.
> 
> > +		writel(ctl, kbc->mmio + KBC_CONTROL_0);
> > +		return IRQ_HANDLED;
> > +	}
> > +
> > +	/* Schedule timer to run when hardware is in continuous polling mode. */
> > +	mod_timer(&kbc->timer, jiffies + kbc->cp_dly_jiffies);
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static int __devinit tegra_kbc_probe(struct platform_device *pdev)
> > +{
> > +	struct tegra_kbc *kbc;
> > +	const struct tegra_kbc_platform_data *pdata = pdev->dev.platform_data;
> > +	struct resource *res;
> > +	int irq;
> > +	int err;
> > +	int rows[KBC_MAX_ROW];
> > +	int cols[KBC_MAX_COL];
> > +	int i, j;
> > +	int nr = 0;
> > +	unsigned int debounce_cnt;
> > +
> > +	if (!pdata)
> > +		return -EINVAL;
> > +
> > +	kbc = kzalloc(sizeof(*kbc), GFP_KERNEL);
> > +	if (!kbc)
> > +		return -ENOMEM;
> > +
> > +	kbc->pdata = pdata;
> > +	kbc->irq = -EINVAL;
> 
> You don't need such assignments for irq.
> 
> > +
> > +	memset(rows, 0, sizeof(rows));
> > +	memset(cols, 0, sizeof(cols));
> > +
> > +	kbc->idev = input_allocate_device();
> > +	if (!kbc->idev) {
> > +		err = -ENOMEM;
> > +		goto fail;
> > +	}
> > +
> > +	debounce_cnt = min_t(unsigned int, pdata->debounce_cnt, 0x3fful);
> > +	kbc->repoll_time = 5 + (16 + debounce_cnt) * nr + pdata->repeat_cnt;
> > +	kbc->repoll_time = (kbc->repoll_time + 31) / 32;
> 
> Care to add note on this equation? Lot's of magic nos. used in this, so they better
> get documented.
> 
> > +
> > +	kbc->idev->evbit[0] = BIT_MASK(EV_KEY);
> > +
> > +	/* Override the default keycodes with the board supplied ones. */
> > +	if (pdata->plain_keycode) {
> > +		kbc->plain_keycode = pdata->plain_keycode;
> > +		kbc->fn_keycode = pdata->fn_keycode;
> > +	} else {
> > +		kbc->plain_keycode = plain_kbd_keycode;
> > +		kbc->fn_keycode = fn_kbd_keycode;
> > +	}
> > +
> > +	for (i = 0; i < KBC_MAX_COL; i++) {
> > +		if (!cols[i])
> > +			continue;
> > +		for (j = 0; j < KBC_MAX_ROW; j++) {
> > +			int keycode;
> > +
> > +			if (!rows[j])
> > +				continue;
> > +
> > +			/* enable all the mapped keys. */
> > +			keycode = tegra_kbc_keycode(kbc, j, i, false);
> > +			if (keycode != -1)
> > +				set_bit(keycode, kbc->idev->keybit);
> > +
> > +			keycode = tegra_kbc_keycode(kbc, j, i, true);
> > +			if (keycode != -1)
> > +				set_bit(keycode, kbc->idev->keybit);
> > +		}
> > +	}
> > +
> > +	setup_timer(&kbc->timer, tegra_kbc_keypress_timer, (unsigned long)kbc);
> > +	/* Initialize the FIFO to invalid entries */
> > +	for (i = 0; i < ARRAY_SIZE(kbc->fifo); i++)
> > +		kbc->fifo[i] = -1;
> > +
> > +	/* keycode FIFO needs to be read atomically; leave local
> > +	 * interrupts disabled when handling KBC interrupt */
> > +	err = request_irq(irq, tegra_kbc_isr, IRQF_TRIGGER_HIGH,
> > +		pdev->name, kbc);
> > +	if (err) {
> > +		dev_err(&pdev->dev, "failed to request keypad IRQ\n");
> > +		goto fail;
> > +	}
> > +	kbc->irq = irq;
> > +
> > +	err = input_register_device(kbc->idev);
> > +	if (err) {
> > +		dev_err(&pdev->dev, "failed to register input device\n");
> > +		goto fail;
> > +	}
> > +
> > +	device_init_wakeup(&pdev->dev, pdata->wakeup);
> > +	return 0;
> > +
> > +fail:
> 
> It is better if you use multiple labels with differing names, as it will
> really improve your error patch and you don't need such if (...) checks against
> each of these resource release operations then. Please check other drivers..
> 
> > +	input_free_device(kbc->idev);
> > +	if (kbc->irq >= 0)
> > +		free_irq(kbc->irq, pdev);
> > +	if (kbc->clk)
> > +		clk_put(kbc->clk);
> > +	if (kbc->mmio)
> > +		iounmap(kbc->mmio);
> 
> 
> 
> > +	kfree(kbc);
> > +	return err;
> > +}
> > +
> > +#ifdef CONFIG_PM
> > +static int tegra_kbc_suspend(struct platform_device *pdev, pm_message_t state)
> > +{
> > +	struct tegra_kbc *kbc = platform_get_drvdata(pdev);
> > +
> > +	if (device_may_wakeup(&pdev->dev)) {
> > +		tegra_kbc_setup_wakekeys(kbc, true);
> > +		enable_irq_wake(kbc->irq);
> > +		/* Forcefully clear the interrupt status */
> > +		writel(0x7, kbc->mmio + KBC_INT_0);
> > +		msleep(30);
> > +	} else {
> > +		mutex_lock(&kbc->idev->mutex);
> > +		tegra_kbc_close(kbc->idev);
> 
> Only if there are any users. Please add that check.
> 
> > +		mutex_unlock(&kbc->idev->mutex);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int tegra_kbc_resume(struct platform_device *pdev)
> > +{
> > +	struct tegra_kbc *kbc = platform_get_drvdata(pdev);
> > +	int err = 0;
> > +
> > +	if (device_may_wakeup(&pdev->dev)) {
> > +		disable_irq_wake(kbc->irq);
> > +		tegra_kbc_setup_wakekeys(kbc, false);
> > +	} else if (kbc->idev->users) {
> > +		mutex_lock(&kbc->idev->mutex);
> > +		err = tegra_kbc_open(kbc->idev);
> 
> As mentioned above.
> 
> > +		mutex_unlock(&kbc->idev->mutex);
> > +	}
> > +
> > +	return err;
> > +}
> > +#endif
> > +
> 
> 
> --
> Sent by a consultant of the Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux