diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-24 21:34:29 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-24 21:34:29 +0400 |
commit | 2c01e7bc46f10e9190818437e564f7e0db875ae9 (patch) | |
tree | 8b06c85d69754f7df27f7fb42520f6e2ceaea907 /drivers/input/keyboard/omap4-keypad.c | |
parent | ab11ca34eea8fda7a1a9302d86f6ef6108ffd68f (diff) | |
parent | e644dae645e167d154c0526358940986682a72b0 (diff) | |
download | linux-2c01e7bc46f10e9190818437e564f7e0db875ae9.tar.xz |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input layer updates from Dmitry Torokhov:
- a bunch of new drivers (DA9052/53 touchscreenn controller, Synaptics
Navpoint, LM8333 keypads, Wacom I2C touhscreen);
- updates to existing touchpad drivers (ALPS, Sntelic);
- Wacom driver now supports Intuos5;
- device-tree bindings in numerous drivers;
- other cleanups and fixes.
Fix annoying conflict in drivers/input/tablet/wacom_wac.c that I think
implies that the input layer device naming is broken, but let's see. I
brough it up with Dmitry.
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (57 commits)
Input: matrix-keymap - fix building keymaps
Input: spear-keyboard - document DT bindings
Input: spear-keyboard - add device tree bindings
Input: matrix-keymap - wire up device tree support
Input: matrix-keymap - uninline and prepare for device tree support
Input: adp5588 - add support for gpio names
Input: omap-keypad - dynamically handle register offsets
Input: synaptics - fix compile warning
MAINTAINERS: adjust input-related patterns
Input: ALPS - switch to using input_mt_report_finger_count
Input: ALPS - add semi-MT support for v4 protocol
Input: Add Synaptics NavPoint (PXA27x SSP/SPI) driver
Input: atmel_mxt_ts - dump each message on just 1 line
Input: atmel_mxt_ts - do not read extra (checksum) byte
Input: atmel_mxt_ts - verify object size in mxt_write_object
Input: atmel_mxt_ts - only allow root to update firmware
Input: atmel_mxt_ts - use CONFIG_PM_SLEEP
Input: sentelic - report device's production serial number
Input: tl6040-vibra - Device Tree support
Input: evdev - properly handle read/write with count 0
...
Diffstat (limited to 'drivers/input/keyboard/omap4-keypad.c')
-rw-r--r-- | drivers/input/keyboard/omap4-keypad.c | 133 |
1 files changed, 99 insertions, 34 deletions
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c index e809ac095a38..aed5f6999ce2 100644 --- a/drivers/input/keyboard/omap4-keypad.c +++ b/drivers/input/keyboard/omap4-keypad.c @@ -68,19 +68,52 @@ #define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF +enum { + KBD_REVISION_OMAP4 = 0, + KBD_REVISION_OMAP5, +}; + struct omap4_keypad { struct input_dev *input; void __iomem *base; - int irq; + unsigned int irq; unsigned int rows; unsigned int cols; + u32 reg_offset; + u32 irqreg_offset; unsigned int row_shift; unsigned char key_state[8]; unsigned short keymap[]; }; +static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset) +{ + return __raw_readl(keypad_data->base + + keypad_data->reg_offset + offset); +} + +static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value) +{ + __raw_writel(value, + keypad_data->base + keypad_data->reg_offset + offset); +} + +static int kbd_read_irqreg(struct omap4_keypad *keypad_data, u32 offset) +{ + return __raw_readl(keypad_data->base + + keypad_data->irqreg_offset + offset); +} + +static void kbd_write_irqreg(struct omap4_keypad *keypad_data, + u32 offset, u32 value) +{ + __raw_writel(value, + keypad_data->base + keypad_data->irqreg_offset + offset); +} + + /* Interrupt handler */ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id) { @@ -91,12 +124,11 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id) u32 *new_state = (u32 *) key_state; /* Disable interrupts */ - __raw_writel(OMAP4_VAL_IRQDISABLE, - keypad_data->base + OMAP4_KBD_IRQENABLE); + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE, + OMAP4_VAL_IRQDISABLE); - *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0); - *(new_state + 1) = __raw_readl(keypad_data->base - + OMAP4_KBD_FULLCODE63_32); + *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0); + *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32); for (row = 0; row < keypad_data->rows; row++) { changed = key_state[row] ^ keypad_data->key_state[row]; @@ -121,12 +153,13 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id) sizeof(keypad_data->key_state)); /* clear pending interrupts */ - __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS), - keypad_data->base + OMAP4_KBD_IRQSTATUS); + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS, + kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS)); /* enable interrupts */ - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY, - keypad_data->base + OMAP4_KBD_IRQENABLE); + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE, + OMAP4_DEF_IRQENABLE_EVENTEN | + OMAP4_DEF_IRQENABLE_LONGKEY); return IRQ_HANDLED; } @@ -139,16 +172,17 @@ static int omap4_keypad_open(struct input_dev *input) disable_irq(keypad_data->irq); - __raw_writel(OMAP4_VAL_FUNCTIONALCFG, - keypad_data->base + OMAP4_KBD_CTRL); - __raw_writel(OMAP4_VAL_DEBOUNCINGTIME, - keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME); - __raw_writel(OMAP4_VAL_IRQDISABLE, - keypad_data->base + OMAP4_KBD_IRQSTATUS); - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY, - keypad_data->base + OMAP4_KBD_IRQENABLE); - __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA, - keypad_data->base + OMAP4_KBD_WAKEUPENABLE); + kbd_writel(keypad_data, OMAP4_KBD_CTRL, + OMAP4_VAL_FUNCTIONALCFG); + kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME, + OMAP4_VAL_DEBOUNCINGTIME); + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS, + OMAP4_VAL_IRQDISABLE); + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE, + OMAP4_DEF_IRQENABLE_EVENTEN | + OMAP4_DEF_IRQENABLE_LONGKEY); + kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE, + OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA); enable_irq(keypad_data->irq); @@ -162,12 +196,12 @@ static void omap4_keypad_close(struct input_dev *input) disable_irq(keypad_data->irq); /* Disable interrupts */ - __raw_writel(OMAP4_VAL_IRQDISABLE, - keypad_data->base + OMAP4_KBD_IRQENABLE); + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE, + OMAP4_VAL_IRQDISABLE); /* clear pending interrupts */ - __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS), - keypad_data->base + OMAP4_KBD_IRQSTATUS); + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS, + kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS)); enable_irq(keypad_data->irq); @@ -182,6 +216,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev) struct resource *res; resource_size_t size; unsigned int row_shift, max_keys; + int rev; int irq; int error; @@ -241,11 +276,40 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev) keypad_data->rows = pdata->rows; keypad_data->cols = pdata->cols; + /* + * 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) { + dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n"); + goto err_unmap; + } + rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION); + rev &= 0x03 << 30; + rev >>= 30; + switch (rev) { + case KBD_REVISION_OMAP4: + keypad_data->reg_offset = 0x00; + keypad_data->irqreg_offset = 0x00; + break; + case KBD_REVISION_OMAP5: + keypad_data->reg_offset = 0x10; + keypad_data->irqreg_offset = 0x0c; + break; + default: + dev_err(&pdev->dev, + "Keypad reports unsupported revision %d", rev); + error = -EINVAL; + goto err_pm_put_sync; + } + /* input device allocation */ keypad_data->input = input_dev = input_allocate_device(); if (!input_dev) { error = -ENOMEM; - goto err_unmap; + goto err_pm_put_sync; } input_dev->name = pdev->name; @@ -258,20 +322,19 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev) input_dev->open = omap4_keypad_open; input_dev->close = omap4_keypad_close; - input_dev->keycode = keypad_data->keymap; - input_dev->keycodesize = sizeof(keypad_data->keymap[0]); - input_dev->keycodemax = max_keys; + error = matrix_keypad_build_keymap(pdata->keymap_data, NULL, + pdata->rows, pdata->cols, + keypad_data->keymap, input_dev); + if (error) { + dev_err(&pdev->dev, "failed to build keymap\n"); + goto err_free_input; + } - __set_bit(EV_KEY, input_dev->evbit); __set_bit(EV_REP, input_dev->evbit); - input_set_capability(input_dev, EV_MSC, MSC_SCAN); input_set_drvdata(input_dev, keypad_data); - matrix_keypad_build_keymap(pdata->keymap_data, row_shift, - input_dev->keycode, input_dev->keybit); - error = request_irq(keypad_data->irq, omap4_keypad_interrupt, IRQF_TRIGGER_RISING, "omap4-keypad", keypad_data); @@ -280,7 +343,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev) goto err_free_input; } - pm_runtime_enable(&pdev->dev); + pm_runtime_put_sync(&pdev->dev); error = input_register_device(keypad_data->input); if (error < 0) { @@ -296,6 +359,8 @@ err_pm_disable: free_irq(keypad_data->irq, keypad_data); err_free_input: input_free_device(input_dev); +err_pm_put_sync: + pm_runtime_put_sync(&pdev->dev); err_unmap: iounmap(keypad_data->base); err_release_mem: |