From 1c407a1b24debecccc42e5a2ae167f058dbb6fba Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Sun, 6 Jan 2013 18:30:21 -0800 Subject: Input: tegra-kbc - fix build warning Fix the following build warning when building driver with CONFIG_PM_SLEEP not selected. tegra-kbc.c:360:13: warning: 'tegra_kbc_set_keypress_interrupt' defined but not used [-Wunused-function] Signed-off-by: Laxman Dewangan Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/tegra-kbc.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/input/keyboard/tegra-kbc.c') diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index c76f96872d31..f1d3ba0dafb2 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -357,18 +357,6 @@ static void tegra_kbc_set_fifo_interrupt(struct tegra_kbc *kbc, bool enable) writel(val, kbc->mmio + KBC_CONTROL_0); } -static void tegra_kbc_set_keypress_interrupt(struct tegra_kbc *kbc, bool enable) -{ - u32 val; - - val = readl(kbc->mmio + KBC_CONTROL_0); - if (enable) - val |= KBC_CONTROL_KEYPRESS_INT_EN; - else - val &= ~KBC_CONTROL_KEYPRESS_INT_EN; - writel(val, kbc->mmio + KBC_CONTROL_0); -} - static void tegra_kbc_keypress_timer(unsigned long data) { struct tegra_kbc *kbc = (struct tegra_kbc *)data; @@ -866,6 +854,18 @@ static int tegra_kbc_remove(struct platform_device *pdev) } #ifdef CONFIG_PM_SLEEP +static void tegra_kbc_set_keypress_interrupt(struct tegra_kbc *kbc, bool enable) +{ + u32 val; + + val = readl(kbc->mmio + KBC_CONTROL_0); + if (enable) + val |= KBC_CONTROL_KEYPRESS_INT_EN; + else + val &= ~KBC_CONTROL_KEYPRESS_INT_EN; + writel(val, kbc->mmio + KBC_CONTROL_0); +} + static int tegra_kbc_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); -- cgit v1.2.3-59-g8ed1b From 00eb81e56a38ffb7839e0e6262e26c20c617d2ab Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Sun, 6 Jan 2013 18:31:20 -0800 Subject: Input: tegra-kbc - use devm_* for resource allocation Use devm_* for memory, clock, irq, input device allocation. This reduces code for freeing these resources. Signed-off-by: Laxman Dewangan Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/tegra-kbc.c | 105 ++++++++++--------------------------- 1 file changed, 27 insertions(+), 78 deletions(-) (limited to 'drivers/input/keyboard/tegra-kbc.c') diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index f1d3ba0dafb2..f79993679070 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -618,7 +618,7 @@ static struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata( if (!np) return NULL; - pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return NULL; @@ -700,33 +700,36 @@ static int tegra_kbc_probe(struct platform_device *pdev) if (!pdata) pdata = tegra_kbc_dt_parse_pdata(pdev); - if (!pdata) + if (!pdata) { + dev_err(&pdev->dev, "Platform data missing\n"); return -EINVAL; - - if (!tegra_kbc_check_pin_cfg(pdata, &pdev->dev, &num_rows)) { - err = -EINVAL; - goto err_free_pdata; } + if (!tegra_kbc_check_pin_cfg(pdata, &pdev->dev, &num_rows)) + return -EINVAL; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "failed to get I/O memory\n"); - err = -ENXIO; - goto err_free_pdata; + return -ENXIO; } irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "failed to get keyboard IRQ\n"); - err = -ENXIO; - goto err_free_pdata; + return -ENXIO; } - kbc = kzalloc(sizeof(*kbc), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!kbc || !input_dev) { - err = -ENOMEM; - goto err_free_mem; + kbc = devm_kzalloc(&pdev->dev, sizeof(*kbc), GFP_KERNEL); + if (!kbc) { + dev_err(&pdev->dev, "failed to alloc memory for kbc\n"); + return -ENOMEM; + } + + input_dev = devm_input_allocate_device(&pdev->dev); + if (!input_dev) { + dev_err(&pdev->dev, "failed to allocate input device\n"); + return -ENOMEM; } kbc->pdata = pdata; @@ -735,25 +738,16 @@ static int tegra_kbc_probe(struct platform_device *pdev) spin_lock_init(&kbc->lock); setup_timer(&kbc->timer, tegra_kbc_keypress_timer, (unsigned long)kbc); - res = request_mem_region(res->start, resource_size(res), pdev->name); - if (!res) { - dev_err(&pdev->dev, "failed to request I/O memory\n"); - err = -EBUSY; - goto err_free_mem; - } - - kbc->mmio = ioremap(res->start, resource_size(res)); + kbc->mmio = devm_request_and_ioremap(&pdev->dev, res); if (!kbc->mmio) { - dev_err(&pdev->dev, "failed to remap I/O memory\n"); - err = -ENXIO; - goto err_free_mem_region; + dev_err(&pdev->dev, "Cannot request memregion/iomap address\n"); + return -EBUSY; } - kbc->clk = clk_get(&pdev->dev, NULL); + kbc->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(kbc->clk)) { dev_err(&pdev->dev, "failed to get keyboard clock\n"); - err = PTR_ERR(kbc->clk); - goto err_iounmap; + return PTR_ERR(kbc->clk); } /* @@ -780,7 +774,7 @@ static int tegra_kbc_probe(struct platform_device *pdev) err = tegra_kbd_setup_keymap(kbc); if (err) { dev_err(&pdev->dev, "failed to setup keymap\n"); - goto err_put_clk; + return err; } __set_bit(EV_REP, input_dev->evbit); @@ -788,11 +782,11 @@ static int tegra_kbc_probe(struct platform_device *pdev) input_set_drvdata(input_dev, kbc); - err = request_irq(kbc->irq, tegra_kbc_isr, + err = devm_request_irq(&pdev->dev, kbc->irq, tegra_kbc_isr, IRQF_NO_SUSPEND | IRQF_TRIGGER_HIGH, pdev->name, kbc); if (err) { dev_err(&pdev->dev, "failed to request keyboard IRQ\n"); - goto err_put_clk; + return err; } disable_irq(kbc->irq); @@ -800,56 +794,12 @@ static int tegra_kbc_probe(struct platform_device *pdev) err = input_register_device(kbc->idev); if (err) { dev_err(&pdev->dev, "failed to register input device\n"); - goto err_free_irq; + return err; } platform_set_drvdata(pdev, kbc); device_init_wakeup(&pdev->dev, pdata->wakeup); - return 0; - -err_free_irq: - free_irq(kbc->irq, pdev); -err_put_clk: - clk_put(kbc->clk); -err_iounmap: - iounmap(kbc->mmio); -err_free_mem_region: - release_mem_region(res->start, resource_size(res)); -err_free_mem: - input_free_device(input_dev); - kfree(kbc); -err_free_pdata: - if (!pdev->dev.platform_data) - kfree(pdata); - - return err; -} - -static int tegra_kbc_remove(struct platform_device *pdev) -{ - struct tegra_kbc *kbc = platform_get_drvdata(pdev); - struct resource *res; - - platform_set_drvdata(pdev, NULL); - - free_irq(kbc->irq, pdev); - clk_put(kbc->clk); - - input_unregister_device(kbc->idev); - iounmap(kbc->mmio); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, resource_size(res)); - - /* - * If we do not have platform data attached to the device we - * allocated it ourselves and thus need to free it. - */ - if (!pdev->dev.platform_data) - kfree(kbc->pdata); - - kfree(kbc); - return 0; } @@ -954,7 +904,6 @@ MODULE_DEVICE_TABLE(of, tegra_kbc_of_match); static struct platform_driver tegra_kbc_driver = { .probe = tegra_kbc_probe, - .remove = tegra_kbc_remove, .driver = { .name = "tegra-kbc", .owner = THIS_MODULE, -- cgit v1.2.3-59-g8ed1b From 88390243a9937f9831aeba5113a8b59bb1d4411a Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Sun, 6 Jan 2013 18:32:22 -0800 Subject: Input: tegra-kbc - add support for rows/columns configuration from dt The NVIDIA's Tegra KBC has maximum 24 pins to make matrix keypad. Any pin can be configured as row or column. The maximum column pin can be 8 and maximum row pin can be 16. Remove the assumption that all first 16 pins will be used as row and remaining as columns and Add the property for configuring pins to either row or column from DT. Update the devicetree binding document accordingly. Signed-off-by: Laxman Dewangan Signed-off-by: Dmitry Torokhov --- .../bindings/input/nvidia,tegra20-kbc.txt | 22 ++++++ drivers/input/keyboard/tegra-kbc.c | 82 +++++++++++++++++----- 2 files changed, 85 insertions(+), 19 deletions(-) (limited to 'drivers/input/keyboard/tegra-kbc.c') diff --git a/Documentation/devicetree/bindings/input/nvidia,tegra20-kbc.txt b/Documentation/devicetree/bindings/input/nvidia,tegra20-kbc.txt index 72683be6de35..2995fae7ee47 100644 --- a/Documentation/devicetree/bindings/input/nvidia,tegra20-kbc.txt +++ b/Documentation/devicetree/bindings/input/nvidia,tegra20-kbc.txt @@ -1,7 +1,18 @@ * Tegra keyboard controller +The key controller has maximum 24 pins to make matrix keypad. Any pin +can be configured as row or column. The maximum column pin can be 8 +and maximum row pins can be 16 for Tegra20/Tegra30. Required properties: - compatible: "nvidia,tegra20-kbc" +- reg: Register base address of KBC. +- interrupts: Interrupt number for the KBC. +- nvidia,kbc-row-pins: The KBC pins which are configured as row. This is an + array of pin numbers which is used as rows. +- nvidia,kbc-col-pins: The KBC pins which are configured as column. This is an + array of pin numbers which is used as column. +- linux,keymap: The keymap for keys as described in the binding document + devicetree/bindings/input/matrix-keymap.txt. Optional properties, in addition to those specified by the shared matrix-keyboard bindings: @@ -19,5 +30,16 @@ Example: keyboard: keyboard { compatible = "nvidia,tegra20-kbc"; reg = <0x7000e200 0x100>; + interrupts = <0 85 0x04>; nvidia,ghost-filter; + nvidia,debounce-delay-ms = <640>; + nvidia,kbc-row-pins = <0 1 2>; /* pin 0, 1, 2 as rows */ + nvidia,kbc-col-pins = <11 12 13>; /* pin 11, 12, 13 as columns */ + linux,keymap = <0x00000074 + 0x00010067 + 0x00020066 + 0x01010068 + 0x02000069 + 0x02010070 + 0x02020071>; }; diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index f79993679070..39ef663bb38f 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -614,13 +614,21 @@ static struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata( struct device_node *np = pdev->dev.of_node; u32 prop; int i; - - if (!np) - return NULL; + u32 num_rows = 0; + u32 num_cols = 0; + u32 cols_cfg[KBC_MAX_GPIO]; + u32 rows_cfg[KBC_MAX_GPIO]; + int proplen; + int ret; + + if (!np) { + dev_err(&pdev->dev, "device tree data is missing\n"); + return ERR_PTR(-ENOENT); + } pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) - return NULL; + return ERR_PTR(-ENOMEM); if (!of_property_read_u32(np, "nvidia,debounce-delay-ms", &prop)) pdata->debounce_cnt = prop; @@ -634,18 +642,55 @@ static struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata( if (of_find_property(np, "nvidia,wakeup-source", NULL)) pdata->wakeup = true; - /* - * All currently known keymaps with device tree support use the same - * pin_cfg, so set it up here. - */ - for (i = 0; i < KBC_MAX_ROW; i++) { - pdata->pin_cfg[i].num = i; - pdata->pin_cfg[i].type = PIN_CFG_ROW; + if (!of_get_property(np, "nvidia,kbc-row-pins", &proplen)) { + dev_err(&pdev->dev, "property nvidia,kbc-row-pins not found\n"); + return ERR_PTR(-ENOENT); + } + num_rows = proplen / sizeof(u32); + + if (!of_get_property(np, "nvidia,kbc-col-pins", &proplen)) { + dev_err(&pdev->dev, "property nvidia,kbc-col-pins not found\n"); + return ERR_PTR(-ENOENT); + } + num_cols = proplen / sizeof(u32); + + if (!of_get_property(np, "linux,keymap", &proplen)) { + dev_err(&pdev->dev, "property linux,keymap not found\n"); + return ERR_PTR(-ENOENT); } - for (i = 0; i < KBC_MAX_COL; i++) { - pdata->pin_cfg[KBC_MAX_ROW + i].num = i; - pdata->pin_cfg[KBC_MAX_ROW + i].type = PIN_CFG_COL; + if (!num_rows || !num_cols || ((num_rows + num_cols) > KBC_MAX_GPIO)) { + dev_err(&pdev->dev, + "keypad rows/columns not porperly specified\n"); + return ERR_PTR(-EINVAL); + } + + /* Set all pins as non-configured */ + for (i = 0; i < KBC_MAX_GPIO; i++) + pdata->pin_cfg[i].type = PIN_CFG_IGNORE; + + ret = of_property_read_u32_array(np, "nvidia,kbc-row-pins", + rows_cfg, num_rows); + if (ret < 0) { + dev_err(&pdev->dev, "Rows configurations are not proper\n"); + return ERR_PTR(-EINVAL); + } + + ret = of_property_read_u32_array(np, "nvidia,kbc-col-pins", + cols_cfg, num_cols); + if (ret < 0) { + dev_err(&pdev->dev, "Cols configurations are not proper\n"); + return ERR_PTR(-EINVAL); + } + + for (i = 0; i < num_rows; i++) { + pdata->pin_cfg[rows_cfg[i]].type = PIN_CFG_ROW; + pdata->pin_cfg[rows_cfg[i]].num = i; + } + + for (i = 0; i < num_cols; i++) { + pdata->pin_cfg[cols_cfg[i]].type = PIN_CFG_COL; + pdata->pin_cfg[cols_cfg[i]].num = i; } return pdata; @@ -654,7 +699,8 @@ static struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata( static inline struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata( struct platform_device *pdev) { - return NULL; + dev_err(&pdev->dev, "platform data is missing\n"); + return ERR_PTR(-EINVAL); } #endif @@ -700,10 +746,8 @@ static int tegra_kbc_probe(struct platform_device *pdev) if (!pdata) pdata = tegra_kbc_dt_parse_pdata(pdev); - if (!pdata) { - dev_err(&pdev->dev, "Platform data missing\n"); - return -EINVAL; - } + if (IS_ERR(pdata)) + return PTR_ERR(pdata); if (!tegra_kbc_check_pin_cfg(pdata, &pdev->dev, &num_rows)) return -EINVAL; -- cgit v1.2.3-59-g8ed1b From 914e597682375ad732d2fedecd855ac637ed7ef7 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Sun, 6 Jan 2013 18:34:48 -0800 Subject: Input: tegra-kbc - remove default keymap Tegra KBC driver have the default key mapping for 16x8 configuration. The key mapping can be provided through platform data or through DT and the mapping varies from platform to platform, hence this default mapping is not so useful. Remove the default mapping to reduce the code lines of the driver. Signed-off-by: Laxman Dewangan Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/tegra-kbc.c | 176 ++----------------------------------- 1 file changed, 7 insertions(+), 169 deletions(-) (limited to 'drivers/input/keyboard/tegra-kbc.c') diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index 39ef663bb38f..4526bdd36022 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -87,147 +87,6 @@ struct tegra_kbc { struct clk *clk; }; -static const u32 tegra_kbc_default_keymap[] = { - KEY(0, 2, KEY_W), - KEY(0, 3, KEY_S), - KEY(0, 4, KEY_A), - KEY(0, 5, KEY_Z), - KEY(0, 7, KEY_FN), - - KEY(1, 7, KEY_LEFTMETA), - - KEY(2, 6, KEY_RIGHTALT), - KEY(2, 7, KEY_LEFTALT), - - KEY(3, 0, KEY_5), - KEY(3, 1, KEY_4), - KEY(3, 2, KEY_R), - KEY(3, 3, KEY_E), - KEY(3, 4, KEY_F), - KEY(3, 5, KEY_D), - KEY(3, 6, KEY_X), - - KEY(4, 0, KEY_7), - KEY(4, 1, KEY_6), - KEY(4, 2, KEY_T), - KEY(4, 3, KEY_H), - KEY(4, 4, KEY_G), - KEY(4, 5, KEY_V), - KEY(4, 6, KEY_C), - KEY(4, 7, KEY_SPACE), - - KEY(5, 0, KEY_9), - KEY(5, 1, KEY_8), - KEY(5, 2, KEY_U), - KEY(5, 3, KEY_Y), - KEY(5, 4, KEY_J), - KEY(5, 5, KEY_N), - KEY(5, 6, KEY_B), - KEY(5, 7, KEY_BACKSLASH), - - KEY(6, 0, KEY_MINUS), - KEY(6, 1, KEY_0), - KEY(6, 2, KEY_O), - KEY(6, 3, KEY_I), - KEY(6, 4, KEY_L), - KEY(6, 5, KEY_K), - KEY(6, 6, KEY_COMMA), - KEY(6, 7, KEY_M), - - KEY(7, 1, KEY_EQUAL), - KEY(7, 2, KEY_RIGHTBRACE), - KEY(7, 3, KEY_ENTER), - KEY(7, 7, KEY_MENU), - - KEY(8, 4, KEY_RIGHTSHIFT), - KEY(8, 5, KEY_LEFTSHIFT), - - KEY(9, 5, KEY_RIGHTCTRL), - KEY(9, 7, KEY_LEFTCTRL), - - KEY(11, 0, KEY_LEFTBRACE), - KEY(11, 1, KEY_P), - KEY(11, 2, KEY_APOSTROPHE), - KEY(11, 3, KEY_SEMICOLON), - KEY(11, 4, KEY_SLASH), - KEY(11, 5, KEY_DOT), - - KEY(12, 0, KEY_F10), - KEY(12, 1, KEY_F9), - KEY(12, 2, KEY_BACKSPACE), - KEY(12, 3, KEY_3), - KEY(12, 4, KEY_2), - KEY(12, 5, KEY_UP), - KEY(12, 6, KEY_PRINT), - KEY(12, 7, KEY_PAUSE), - - KEY(13, 0, KEY_INSERT), - KEY(13, 1, KEY_DELETE), - KEY(13, 3, KEY_PAGEUP), - KEY(13, 4, KEY_PAGEDOWN), - KEY(13, 5, KEY_RIGHT), - KEY(13, 6, KEY_DOWN), - KEY(13, 7, KEY_LEFT), - - KEY(14, 0, KEY_F11), - KEY(14, 1, KEY_F12), - KEY(14, 2, KEY_F8), - KEY(14, 3, KEY_Q), - KEY(14, 4, KEY_F4), - KEY(14, 5, KEY_F3), - KEY(14, 6, KEY_1), - KEY(14, 7, KEY_F7), - - KEY(15, 0, KEY_ESC), - KEY(15, 1, KEY_GRAVE), - KEY(15, 2, KEY_F5), - KEY(15, 3, KEY_TAB), - KEY(15, 4, KEY_F1), - KEY(15, 5, KEY_F2), - KEY(15, 6, KEY_CAPSLOCK), - KEY(15, 7, KEY_F6), - - /* Software Handled Function Keys */ - KEY(20, 0, KEY_KP7), - - KEY(21, 0, KEY_KP9), - KEY(21, 1, KEY_KP8), - KEY(21, 2, KEY_KP4), - KEY(21, 4, KEY_KP1), - - KEY(22, 1, KEY_KPSLASH), - KEY(22, 2, KEY_KP6), - KEY(22, 3, KEY_KP5), - KEY(22, 4, KEY_KP3), - KEY(22, 5, KEY_KP2), - KEY(22, 7, KEY_KP0), - - KEY(27, 1, KEY_KPASTERISK), - KEY(27, 3, KEY_KPMINUS), - KEY(27, 4, KEY_KPPLUS), - KEY(27, 5, KEY_KPDOT), - - KEY(28, 5, KEY_VOLUMEUP), - - KEY(29, 3, KEY_HOME), - KEY(29, 4, KEY_END), - KEY(29, 5, KEY_BRIGHTNESSDOWN), - KEY(29, 6, KEY_VOLUMEDOWN), - KEY(29, 7, KEY_BRIGHTNESSUP), - - KEY(30, 0, KEY_NUMLOCK), - KEY(30, 1, KEY_SCROLLLOCK), - KEY(30, 2, KEY_MUTE), - - KEY(31, 4, KEY_HELP), -}; - -static const -struct matrix_keymap_data tegra_kbc_default_keymap_data = { - .keymap = tegra_kbc_default_keymap, - .keymap_size = ARRAY_SIZE(tegra_kbc_default_keymap), -}; - static void tegra_kbc_report_released_keys(struct input_dev *input, unsigned short old_keycodes[], unsigned int old_num_keys, @@ -704,33 +563,6 @@ static inline struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata( } #endif -static int tegra_kbd_setup_keymap(struct tegra_kbc *kbc) -{ - const struct tegra_kbc_platform_data *pdata = kbc->pdata; - const struct matrix_keymap_data *keymap_data = pdata->keymap_data; - unsigned int keymap_rows = KBC_MAX_KEY; - int retval; - - if (keymap_data && pdata->use_fn_map) - keymap_rows *= 2; - - retval = matrix_keypad_build_keymap(keymap_data, NULL, - keymap_rows, KBC_MAX_COL, - kbc->keycode, kbc->idev); - if (retval == -ENOSYS || retval == -ENOENT) { - /* - * If there is no OF support in kernel or keymap - * property is missing, use default keymap. - */ - retval = matrix_keypad_build_keymap( - &tegra_kbc_default_keymap_data, NULL, - keymap_rows, KBC_MAX_COL, - kbc->keycode, kbc->idev); - } - - return retval; -} - static int tegra_kbc_probe(struct platform_device *pdev) { const struct tegra_kbc_platform_data *pdata = pdev->dev.platform_data; @@ -742,6 +574,7 @@ static int tegra_kbc_probe(struct platform_device *pdev) int num_rows = 0; unsigned int debounce_cnt; unsigned int scan_time_rows; + unsigned int keymap_rows = KBC_MAX_KEY; if (!pdata) pdata = tegra_kbc_dt_parse_pdata(pdev); @@ -815,7 +648,12 @@ static int tegra_kbc_probe(struct platform_device *pdev) input_dev->open = tegra_kbc_open; input_dev->close = tegra_kbc_close; - err = tegra_kbd_setup_keymap(kbc); + if (pdata->keymap_data && pdata->use_fn_map) + keymap_rows *= 2; + + err = matrix_keypad_build_keymap(pdata->keymap_data, NULL, + keymap_rows, KBC_MAX_COL, + kbc->keycode, input_dev); if (err) { dev_err(&pdev->dev, "failed to setup keymap\n"); return err; -- cgit v1.2.3-59-g8ed1b From 9eee07d39fa606a191ae65d3c0e12771a80e70ca Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 15 Feb 2013 17:04:12 -0800 Subject: Input: tegra-kbc - require CONFIG_OF, remove platform data Tegra only supports, and always enables, device tree. Remove all ifdefs and runtime checks for DT support from the driver. Platform data is therefore no longer required. Delete the header that defines it, and rework the driver to parse the device tree directly into struct tegra_kbc. Signed-off-by: Stephen Warren Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 2 +- drivers/input/keyboard/tegra-kbc.c | 195 +++++++++++++++++-------------------- include/linux/input/tegra_kbc.h | 62 ------------ 3 files changed, 93 insertions(+), 166 deletions(-) delete mode 100644 include/linux/input/tegra_kbc.h (limited to 'drivers/input/keyboard/tegra-kbc.c') diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 72377737eec8..992137cf3a64 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -420,7 +420,7 @@ config KEYBOARD_NOMADIK config KEYBOARD_TEGRA tristate "NVIDIA Tegra internal matrix keyboard controller support" - depends on ARCH_TEGRA + depends on ARCH_TEGRA && OF select INPUT_MATRIXKMAP help Say Y here if you want to use a matrix keyboard connected directly diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index 4526bdd36022..d89e7d392d1e 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -29,9 +29,16 @@ #include #include #include -#include +#include #include +#define KBC_MAX_GPIO 24 +#define KBC_MAX_KPENT 8 + +#define KBC_MAX_ROW 16 +#define KBC_MAX_COL 8 +#define KBC_MAX_KEY (KBC_MAX_ROW * KBC_MAX_COL) + #define KBC_MAX_DEBOUNCE_CNT 0x3ffu /* KBC row scan time and delay for beginning the row scan. */ @@ -67,10 +74,27 @@ #define KBC_ROW_SHIFT 3 +enum tegra_pin_type { + PIN_CFG_IGNORE, + PIN_CFG_COL, + PIN_CFG_ROW, +}; + +struct tegra_kbc_pin_cfg { + enum tegra_pin_type type; + unsigned char num; +}; + struct tegra_kbc { + struct device *dev; + unsigned int debounce_cnt; + unsigned int repeat_cnt; + struct tegra_kbc_pin_cfg pin_cfg[KBC_MAX_GPIO]; + const struct matrix_keymap_data *keymap_data; + bool wakeup; void __iomem *mmio; struct input_dev *idev; - unsigned int irq; + int irq; spinlock_t lock; unsigned int repoll_dly; unsigned long cp_dly_jiffies; @@ -78,7 +102,6 @@ struct tegra_kbc { bool use_fn_map; bool use_ghost_filter; bool keypress_caused_wake; - const struct tegra_kbc_platform_data *pdata; unsigned short keycode[KBC_MAX_KEY * 2]; unsigned short current_keys[KBC_MAX_KPENT]; unsigned int num_pressed_keys; @@ -286,12 +309,11 @@ static irqreturn_t tegra_kbc_isr(int irq, void *args) static void tegra_kbc_setup_wakekeys(struct tegra_kbc *kbc, bool filter) { - const struct tegra_kbc_platform_data *pdata = kbc->pdata; int i; unsigned int rst_val; /* Either mask all keys or none. */ - rst_val = (filter && !pdata->wakeup) ? ~0 : 0; + rst_val = (filter && !kbc->wakeup) ? ~0 : 0; for (i = 0; i < KBC_MAX_ROW; i++) writel(rst_val, kbc->mmio + KBC_ROW0_MASK_0 + i * 4); @@ -299,7 +321,6 @@ static void tegra_kbc_setup_wakekeys(struct tegra_kbc *kbc, bool filter) static void tegra_kbc_config_pins(struct tegra_kbc *kbc) { - const struct tegra_kbc_platform_data *pdata = kbc->pdata; int i; for (i = 0; i < KBC_MAX_GPIO; i++) { @@ -315,13 +336,13 @@ static void tegra_kbc_config_pins(struct tegra_kbc *kbc) row_cfg &= ~r_mask; col_cfg &= ~c_mask; - switch (pdata->pin_cfg[i].type) { + switch (kbc->pin_cfg[i].type) { case PIN_CFG_ROW: - row_cfg |= ((pdata->pin_cfg[i].num << 1) | 1) << r_shft; + row_cfg |= ((kbc->pin_cfg[i].num << 1) | 1) << r_shft; break; case PIN_CFG_COL: - col_cfg |= ((pdata->pin_cfg[i].num << 1) | 1) << c_shft; + col_cfg |= ((kbc->pin_cfg[i].num << 1) | 1) << c_shft; break; case PIN_CFG_IGNORE: @@ -335,7 +356,6 @@ static void tegra_kbc_config_pins(struct tegra_kbc *kbc) static int tegra_kbc_start(struct tegra_kbc *kbc) { - const struct tegra_kbc_platform_data *pdata = kbc->pdata; unsigned int debounce_cnt; u32 val = 0; @@ -350,10 +370,10 @@ static int tegra_kbc_start(struct tegra_kbc *kbc) tegra_kbc_config_pins(kbc); tegra_kbc_setup_wakekeys(kbc, false); - writel(pdata->repeat_cnt, kbc->mmio + KBC_RPT_DLY_0); + writel(kbc->repeat_cnt, kbc->mmio + KBC_RPT_DLY_0); /* Keyboard debounce count is maximum of 12 bits. */ - debounce_cnt = min(pdata->debounce_cnt, KBC_MAX_DEBOUNCE_CNT); + debounce_cnt = min(kbc->debounce_cnt, KBC_MAX_DEBOUNCE_CNT); val = KBC_DEBOUNCE_CNT_SHIFT(debounce_cnt); val |= KBC_FIFO_TH_CNT_SHIFT(1); /* set fifo interrupt threshold to 1 */ val |= KBC_CONTROL_FIFO_CNT_INT_EN; /* interrupt on FIFO threshold */ @@ -420,21 +440,20 @@ static void tegra_kbc_close(struct input_dev *dev) return tegra_kbc_stop(kbc); } -static bool -tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata, - struct device *dev, unsigned int *num_rows) +static bool tegra_kbc_check_pin_cfg(const struct tegra_kbc *kbc, + unsigned int *num_rows) { int i; *num_rows = 0; for (i = 0; i < KBC_MAX_GPIO; i++) { - const struct tegra_kbc_pin_cfg *pin_cfg = &pdata->pin_cfg[i]; + const struct tegra_kbc_pin_cfg *pin_cfg = &kbc->pin_cfg[i]; switch (pin_cfg->type) { case PIN_CFG_ROW: if (pin_cfg->num >= KBC_MAX_ROW) { - dev_err(dev, + dev_err(kbc->dev, "pin_cfg[%d]: invalid row number %d\n", i, pin_cfg->num); return false; @@ -444,7 +463,7 @@ tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata, case PIN_CFG_COL: if (pin_cfg->num >= KBC_MAX_COL) { - dev_err(dev, + dev_err(kbc->dev, "pin_cfg[%d]: invalid column number %d\n", i, pin_cfg->num); return false; @@ -455,7 +474,7 @@ tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata, break; default: - dev_err(dev, + dev_err(kbc->dev, "pin_cfg[%d]: invalid entry type %d\n", pin_cfg->type, pin_cfg->num); return false; @@ -465,12 +484,9 @@ tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata, return true; } -#ifdef CONFIG_OF -static struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata( - struct platform_device *pdev) +static int tegra_kbc_parse_dt(struct tegra_kbc *kbc) { - struct tegra_kbc_platform_data *pdata; - struct device_node *np = pdev->dev.of_node; + struct device_node *np = kbc->dev->of_node; u32 prop; int i; u32 num_rows = 0; @@ -480,109 +496,96 @@ static struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata( int proplen; int ret; - if (!np) { - dev_err(&pdev->dev, "device tree data is missing\n"); - return ERR_PTR(-ENOENT); - } - - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return ERR_PTR(-ENOMEM); - if (!of_property_read_u32(np, "nvidia,debounce-delay-ms", &prop)) - pdata->debounce_cnt = prop; + kbc->debounce_cnt = prop; if (!of_property_read_u32(np, "nvidia,repeat-delay-ms", &prop)) - pdata->repeat_cnt = prop; + kbc->repeat_cnt = prop; if (of_find_property(np, "nvidia,needs-ghost-filter", NULL)) - pdata->use_ghost_filter = true; + kbc->use_ghost_filter = true; if (of_find_property(np, "nvidia,wakeup-source", NULL)) - pdata->wakeup = true; + kbc->wakeup = true; if (!of_get_property(np, "nvidia,kbc-row-pins", &proplen)) { - dev_err(&pdev->dev, "property nvidia,kbc-row-pins not found\n"); - return ERR_PTR(-ENOENT); + dev_err(kbc->dev, "property nvidia,kbc-row-pins not found\n"); + return -ENOENT; } num_rows = proplen / sizeof(u32); if (!of_get_property(np, "nvidia,kbc-col-pins", &proplen)) { - dev_err(&pdev->dev, "property nvidia,kbc-col-pins not found\n"); - return ERR_PTR(-ENOENT); + dev_err(kbc->dev, "property nvidia,kbc-col-pins not found\n"); + return -ENOENT; } num_cols = proplen / sizeof(u32); if (!of_get_property(np, "linux,keymap", &proplen)) { - dev_err(&pdev->dev, "property linux,keymap not found\n"); - return ERR_PTR(-ENOENT); + dev_err(kbc->dev, "property linux,keymap not found\n"); + return -ENOENT; } if (!num_rows || !num_cols || ((num_rows + num_cols) > KBC_MAX_GPIO)) { - dev_err(&pdev->dev, + dev_err(kbc->dev, "keypad rows/columns not porperly specified\n"); - return ERR_PTR(-EINVAL); + return -EINVAL; } /* Set all pins as non-configured */ for (i = 0; i < KBC_MAX_GPIO; i++) - pdata->pin_cfg[i].type = PIN_CFG_IGNORE; + kbc->pin_cfg[i].type = PIN_CFG_IGNORE; ret = of_property_read_u32_array(np, "nvidia,kbc-row-pins", rows_cfg, num_rows); if (ret < 0) { - dev_err(&pdev->dev, "Rows configurations are not proper\n"); - return ERR_PTR(-EINVAL); + dev_err(kbc->dev, "Rows configurations are not proper\n"); + return -EINVAL; } ret = of_property_read_u32_array(np, "nvidia,kbc-col-pins", cols_cfg, num_cols); if (ret < 0) { - dev_err(&pdev->dev, "Cols configurations are not proper\n"); - return ERR_PTR(-EINVAL); + dev_err(kbc->dev, "Cols configurations are not proper\n"); + return -EINVAL; } for (i = 0; i < num_rows; i++) { - pdata->pin_cfg[rows_cfg[i]].type = PIN_CFG_ROW; - pdata->pin_cfg[rows_cfg[i]].num = i; + kbc->pin_cfg[rows_cfg[i]].type = PIN_CFG_ROW; + kbc->pin_cfg[rows_cfg[i]].num = i; } for (i = 0; i < num_cols; i++) { - pdata->pin_cfg[cols_cfg[i]].type = PIN_CFG_COL; - pdata->pin_cfg[cols_cfg[i]].num = i; + kbc->pin_cfg[cols_cfg[i]].type = PIN_CFG_COL; + kbc->pin_cfg[cols_cfg[i]].num = i; } - return pdata; -} -#else -static inline struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata( - struct platform_device *pdev) -{ - dev_err(&pdev->dev, "platform data is missing\n"); - return ERR_PTR(-EINVAL); + return 0; } -#endif static int tegra_kbc_probe(struct platform_device *pdev) { - const struct tegra_kbc_platform_data *pdata = pdev->dev.platform_data; struct tegra_kbc *kbc; - struct input_dev *input_dev; struct resource *res; - int irq; int err; int num_rows = 0; unsigned int debounce_cnt; unsigned int scan_time_rows; unsigned int keymap_rows = KBC_MAX_KEY; - if (!pdata) - pdata = tegra_kbc_dt_parse_pdata(pdev); + kbc = devm_kzalloc(&pdev->dev, sizeof(*kbc), GFP_KERNEL); + if (!kbc) { + dev_err(&pdev->dev, "failed to alloc memory for kbc\n"); + return -ENOMEM; + } + + kbc->dev = &pdev->dev; + spin_lock_init(&kbc->lock); - if (IS_ERR(pdata)) - return PTR_ERR(pdata); + err = tegra_kbc_parse_dt(kbc); + if (err) + return err; - if (!tegra_kbc_check_pin_cfg(pdata, &pdev->dev, &num_rows)) + if (!tegra_kbc_check_pin_cfg(kbc, &num_rows)) return -EINVAL; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -591,28 +594,18 @@ static int tegra_kbc_probe(struct platform_device *pdev) return -ENXIO; } - irq = platform_get_irq(pdev, 0); - if (irq < 0) { + kbc->irq = platform_get_irq(pdev, 0); + if (kbc->irq < 0) { dev_err(&pdev->dev, "failed to get keyboard IRQ\n"); return -ENXIO; } - kbc = devm_kzalloc(&pdev->dev, sizeof(*kbc), GFP_KERNEL); - if (!kbc) { - dev_err(&pdev->dev, "failed to alloc memory for kbc\n"); - return -ENOMEM; - } - - input_dev = devm_input_allocate_device(&pdev->dev); - if (!input_dev) { + kbc->idev = devm_input_allocate_device(&pdev->dev); + if (!kbc->idev) { dev_err(&pdev->dev, "failed to allocate input device\n"); return -ENOMEM; } - kbc->pdata = pdata; - kbc->idev = input_dev; - kbc->irq = irq; - spin_lock_init(&kbc->lock); setup_timer(&kbc->timer, tegra_kbc_keypress_timer, (unsigned long)kbc); kbc->mmio = devm_request_and_ioremap(&pdev->dev, res); @@ -633,36 +626,32 @@ static int tegra_kbc_probe(struct platform_device *pdev) * the rows. There is an additional delay before the row scanning * starts. The repoll delay is computed in milliseconds. */ - debounce_cnt = min(pdata->debounce_cnt, KBC_MAX_DEBOUNCE_CNT); + debounce_cnt = min(kbc->debounce_cnt, KBC_MAX_DEBOUNCE_CNT); scan_time_rows = (KBC_ROW_SCAN_TIME + debounce_cnt) * num_rows; - kbc->repoll_dly = KBC_ROW_SCAN_DLY + scan_time_rows + pdata->repeat_cnt; + kbc->repoll_dly = KBC_ROW_SCAN_DLY + scan_time_rows + kbc->repeat_cnt; kbc->repoll_dly = DIV_ROUND_UP(kbc->repoll_dly, KBC_CYCLE_MS); - kbc->wakeup_key = pdata->wakeup_key; - kbc->use_fn_map = pdata->use_fn_map; - kbc->use_ghost_filter = pdata->use_ghost_filter; - - input_dev->name = pdev->name; - input_dev->id.bustype = BUS_HOST; - input_dev->dev.parent = &pdev->dev; - input_dev->open = tegra_kbc_open; - input_dev->close = tegra_kbc_close; + kbc->idev->name = pdev->name; + kbc->idev->id.bustype = BUS_HOST; + kbc->idev->dev.parent = &pdev->dev; + kbc->idev->open = tegra_kbc_open; + kbc->idev->close = tegra_kbc_close; - if (pdata->keymap_data && pdata->use_fn_map) + if (kbc->keymap_data && kbc->use_fn_map) keymap_rows *= 2; - err = matrix_keypad_build_keymap(pdata->keymap_data, NULL, + err = matrix_keypad_build_keymap(kbc->keymap_data, NULL, keymap_rows, KBC_MAX_COL, - kbc->keycode, input_dev); + kbc->keycode, kbc->idev); if (err) { dev_err(&pdev->dev, "failed to setup keymap\n"); return err; } - __set_bit(EV_REP, input_dev->evbit); - input_set_capability(input_dev, EV_MSC, MSC_SCAN); + __set_bit(EV_REP, kbc->idev->evbit); + input_set_capability(kbc->idev, EV_MSC, MSC_SCAN); - input_set_drvdata(input_dev, kbc); + input_set_drvdata(kbc->idev, kbc); err = devm_request_irq(&pdev->dev, kbc->irq, tegra_kbc_isr, IRQF_NO_SUSPEND | IRQF_TRIGGER_HIGH, pdev->name, kbc); @@ -680,7 +669,7 @@ static int tegra_kbc_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, kbc); - device_init_wakeup(&pdev->dev, pdata->wakeup); + device_init_wakeup(&pdev->dev, kbc->wakeup); return 0; } diff --git a/include/linux/input/tegra_kbc.h b/include/linux/input/tegra_kbc.h deleted file mode 100644 index a13025612939..000000000000 --- a/include/linux/input/tegra_kbc.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Platform definitions for tegra-kbc keyboard input driver - * - * Copyright (c) 2010-2011, NVIDIA Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef ASMARM_ARCH_TEGRA_KBC_H -#define ASMARM_ARCH_TEGRA_KBC_H - -#include -#include - -#define KBC_MAX_GPIO 24 -#define KBC_MAX_KPENT 8 - -#define KBC_MAX_ROW 16 -#define KBC_MAX_COL 8 -#define KBC_MAX_KEY (KBC_MAX_ROW * KBC_MAX_COL) - -enum tegra_pin_type { - PIN_CFG_IGNORE, - PIN_CFG_COL, - PIN_CFG_ROW, -}; - -struct tegra_kbc_pin_cfg { - enum tegra_pin_type type; - unsigned char num; -}; - -struct tegra_kbc_wake_key { - u8 row:4; - u8 col:4; -}; - -struct tegra_kbc_platform_data { - unsigned int debounce_cnt; - unsigned int repeat_cnt; - - struct tegra_kbc_pin_cfg pin_cfg[KBC_MAX_GPIO]; - const struct matrix_keymap_data *keymap_data; - - u32 wakeup_key; - bool wakeup; - bool use_fn_map; - bool use_ghost_filter; -}; -#endif -- cgit v1.2.3-59-g8ed1b