diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-04-03 09:26:49 -0700 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-04-03 09:26:49 -0700 |
commit | 692d96552c9a86a919fe6b5b82288a6c77c015a5 (patch) | |
tree | a9e49c040d361ea2293a8966832378def5a06714 /drivers/input | |
parent | e4dbedc7eac7da9db363a36f2bd4366962eeefcc (diff) | |
parent | e2c3ecf0ea8e87c5209371af7da107ebc47a5639 (diff) |
Merge branch 'next' into for-linus
First round of input updates for 3.15.
Diffstat (limited to 'drivers/input')
30 files changed, 1653 insertions, 1231 deletions
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index a673c9f3a0b9..76842d7dc2e3 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -151,6 +151,18 @@ config KEYBOARD_BFIN To compile this driver as a module, choose M here: the module will be called bf54x-keys. +config KEYBOARD_CLPS711X + tristate "CLPS711X Keypad support" + depends on OF_GPIO && (ARCH_CLPS711X || COMPILE_TEST) + select INPUT_MATRIXKMAP + select INPUT_POLLDEV + help + Say Y here to enable the matrix keypad on the Cirrus Logic + CLPS711X CPUs. + + To compile this driver as a module, choose M here: the + module will be called clps711x-keypad. + config KEYBOARD_LKKBD tristate "DECstation/VAXstation LK201/LK401 keyboard" select SERIO @@ -595,16 +607,6 @@ config KEYBOARD_TC3589X To compile this driver as a module, choose M here: the module will be called tc3589x-keypad. -config KEYBOARD_TNETV107X - tristate "TI TNETV107X keypad support" - depends on ARCH_DAVINCI_TNETV107X - select INPUT_MATRIXKMAP - help - Say Y here if you want to use the TNETV107X keypad. - - To compile this driver as a module, choose M here: the - module will be called tnetv107x-keypad. - config KEYBOARD_TWL4030 tristate "TI TWL4030/TWL5030/TPS659x0 keypad support" depends on TWL4030_CORE diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index a699b6172303..11cff7b84b47 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o +obj-$(CONFIG_KEYBOARD_CLPS711X) += clps711x-keypad.o obj-$(CONFIG_KEYBOARD_CROS_EC) += cros_ec_keyb.o obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o @@ -53,7 +54,6 @@ obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o obj-$(CONFIG_KEYBOARD_TC3589X) += tc3589x-keypad.o obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o -obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o diff --git a/drivers/input/keyboard/clps711x-keypad.c b/drivers/input/keyboard/clps711x-keypad.c new file mode 100644 index 000000000000..3955aecee44b --- /dev/null +++ b/drivers/input/keyboard/clps711x-keypad.c @@ -0,0 +1,207 @@ +/* + * Cirrus Logic CLPS711X Keypad driver + * + * Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru> + * + * 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. + */ + +#include <linux/input.h> +#include <linux/input-polldev.h> +#include <linux/module.h> +#include <linux/of_gpio.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/sched.h> +#include <linux/input/matrix_keypad.h> +#include <linux/mfd/syscon.h> +#include <linux/mfd/syscon/clps711x.h> + +#define CLPS711X_KEYPAD_COL_COUNT 8 + +struct clps711x_gpio_data { + struct gpio_desc *desc; + DECLARE_BITMAP(last_state, CLPS711X_KEYPAD_COL_COUNT); +}; + +struct clps711x_keypad_data { + struct regmap *syscon; + int row_count; + unsigned int row_shift; + struct clps711x_gpio_data *gpio_data; +}; + +static void clps711x_keypad_poll(struct input_polled_dev *dev) +{ + const unsigned short *keycodes = dev->input->keycode; + struct clps711x_keypad_data *priv = dev->private; + bool sync = false; + int col, row; + + for (col = 0; col < CLPS711X_KEYPAD_COL_COUNT; col++) { + /* Assert column */ + regmap_update_bits(priv->syscon, SYSCON_OFFSET, + SYSCON1_KBDSCAN_MASK, + SYSCON1_KBDSCAN(8 + col)); + + /* Scan rows */ + for (row = 0; row < priv->row_count; row++) { + struct clps711x_gpio_data *data = &priv->gpio_data[row]; + bool state, state1; + + /* Read twice for protection against fluctuations */ + do { + state = gpiod_get_value_cansleep(data->desc); + cond_resched(); + state1 = gpiod_get_value_cansleep(data->desc); + } while (state != state1); + + if (test_bit(col, data->last_state) != state) { + int code = MATRIX_SCAN_CODE(row, col, + priv->row_shift); + + if (state) { + set_bit(col, data->last_state); + input_event(dev->input, EV_MSC, + MSC_SCAN, code); + } else { + clear_bit(col, data->last_state); + } + + if (keycodes[code]) + input_report_key(dev->input, + keycodes[code], state); + sync = true; + } + } + + /* Set all columns to low */ + regmap_update_bits(priv->syscon, SYSCON_OFFSET, + SYSCON1_KBDSCAN_MASK, SYSCON1_KBDSCAN(1)); + } + + if (sync) + input_sync(dev->input); +} + +static int clps711x_keypad_probe(struct platform_device *pdev) +{ + struct clps711x_keypad_data *priv; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct input_polled_dev *poll_dev; + u32 poll_interval; + int i, err; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->syscon = + syscon_regmap_lookup_by_compatible("cirrus,clps711x-syscon1"); + if (IS_ERR(priv->syscon)) + return PTR_ERR(priv->syscon); + + priv->row_count = of_gpio_named_count(np, "row-gpios"); + if (priv->row_count < 1) + return -EINVAL; + + priv->gpio_data = devm_kzalloc(dev, + sizeof(*priv->gpio_data) * priv->row_count, + GFP_KERNEL); + if (!priv->gpio_data) + return -ENOMEM; + + priv->row_shift = get_count_order(CLPS711X_KEYPAD_COL_COUNT); + + for (i = 0; i < priv->row_count; i++) { + struct clps711x_gpio_data *data = &priv->gpio_data[i]; + + data->desc = devm_gpiod_get_index(dev, "row", i); + if (!data->desc) + return -EINVAL; + + if (IS_ERR(data->desc)) + return PTR_ERR(data->desc); + + gpiod_direction_input(data->desc); + } + + err = of_property_read_u32(np, "poll-interval", &poll_interval); + if (err) + return err; + + poll_dev = input_allocate_polled_device(); + if (!poll_dev) + return -ENOMEM; + + poll_dev->private = priv; + poll_dev->poll = clps711x_keypad_poll; + poll_dev->poll_interval = poll_interval; + poll_dev->input->name = pdev->name; + poll_dev->input->dev.parent = dev; + poll_dev->input->id.bustype = BUS_HOST; + poll_dev->input->id.vendor = 0x0001; + poll_dev->input->id.product = 0x0001; + poll_dev->input->id.version = 0x0100; + + err = matrix_keypad_build_keymap(NULL, NULL, priv->row_count, + CLPS711X_KEYPAD_COL_COUNT, + NULL, poll_dev->input); + if (err) + goto out_err; + + input_set_capability(poll_dev->input, EV_MSC, MSC_SCAN); + if (of_property_read_bool(np, "autorepeat")) + __set_bit(EV_REP, poll_dev->input->evbit); + + platform_set_drvdata(pdev, poll_dev); + + /* Set all columns to low */ + regmap_update_bits(priv->syscon, SYSCON_OFFSET, SYSCON1_KBDSCAN_MASK, + SYSCON1_KBDSCAN(1)); + + err = input_register_polled_device(poll_dev); + if (err) + goto out_err; + + return 0; + +out_err: + input_free_polled_device(poll_dev); + return err; +} + +static int clps711x_keypad_remove(struct platform_device *pdev) +{ + struct input_polled_dev *poll_dev = platform_get_drvdata(pdev); + + input_unregister_polled_device(poll_dev); + input_free_polled_device(poll_dev); + + return 0; +} + +static struct of_device_id clps711x_keypad_of_match[] = { + { .compatible = "cirrus,clps711x-keypad", }, + { } +}; +MODULE_DEVICE_TABLE(of, clps711x_keypad_of_match); + +static struct platform_driver clps711x_keypad_driver = { + .driver = { + .name = "clps711x-keypad", + .owner = THIS_MODULE, + .of_match_table = clps711x_keypad_of_match, + }, + .probe = clps711x_keypad_probe, + .remove = clps711x_keypad_remove, +}; +module_platform_driver(clps711x_keypad_driver); + +MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>"); +MODULE_DESCRIPTION("Cirrus Logic CLPS711X Keypad driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index cbf4f8038cba..97ec33572e56 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c @@ -439,7 +439,7 @@ static int imx_keypad_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "no irq defined in platform data\n"); - return -EINVAL; + return irq; } input_dev = devm_input_allocate_device(&pdev->dev); @@ -449,7 +449,7 @@ static int imx_keypad_probe(struct platform_device *pdev) } keypad = devm_kzalloc(&pdev->dev, sizeof(struct imx_keypad), - GFP_KERNEL); + GFP_KERNEL); if (!keypad) { dev_err(&pdev->dev, "not enough memory for driver data\n"); return -ENOMEM; diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c index 2c9f19ac35ea..80c6b0ef3fc8 100644 --- a/drivers/input/keyboard/pmic8xxx-keypad.c +++ b/drivers/input/keyboard/pmic8xxx-keypad.c @@ -19,10 +19,9 @@ #include <linux/bitops.h> #include <linux/delay.h> #include <linux/mutex.h> - -#include <linux/mfd/pm8xxx/core.h> -#include <linux/mfd/pm8xxx/gpio.h> -#include <linux/input/pmic8xxx-keypad.h> +#include <linux/regmap.h> +#include <linux/of.h> +#include <linux/input/matrix_keypad.h> #define PM8XXX_MAX_ROWS 18 #define PM8XXX_MAX_COLS 8 @@ -85,8 +84,10 @@ /** * struct pmic8xxx_kp - internal keypad data structure - * @pdata - keypad platform data pointer + * @num_cols - number of columns of keypad + * @num_rows - number of row of keypad * @input - input device pointer for keypad + * @regmap - regmap handle * @key_sense_irq - key press/release irq number * @key_stuck_irq - key stuck notification irq number * @keycodes - array to hold the key codes @@ -96,8 +97,10 @@ * @ctrl_reg - control register value */ struct pmic8xxx_kp { - const struct pm8xxx_keypad_platform_data *pdata; + unsigned int num_rows; + unsigned int num_cols; struct input_dev *input; + struct regmap *regmap; int key_sense_irq; int key_stuck_irq; @@ -110,40 +113,13 @@ struct pmic8xxx_kp { u8 ctrl_reg; }; -static int pmic8xxx_kp_write_u8(struct pmic8xxx_kp *kp, - u8 data, u16 reg) -{ - int rc; - - rc = pm8xxx_writeb(kp->dev->parent, reg, data); - return rc; -} - -static int pmic8xxx_kp_read(struct pmic8xxx_kp *kp, - u8 *data, u16 reg, unsigned num_bytes) -{ - int rc; - - rc = pm8xxx_read_buf(kp->dev->parent, reg, data, num_bytes); - return rc; -} - -static int pmic8xxx_kp_read_u8(struct pmic8xxx_kp *kp, - u8 *data, u16 reg) -{ - int rc; - - rc = pmic8xxx_kp_read(kp, data, reg, 1); - return rc; -} - static u8 pmic8xxx_col_state(struct pmic8xxx_kp *kp, u8 col) { /* all keys pressed on that particular row? */ if (col == 0x00) - return 1 << kp->pdata->num_cols; + return 1 << kp->num_cols; else - return col & ((1 << kp->pdata->num_cols) - 1); + return col & ((1 << kp->num_cols) - 1); } /* @@ -161,9 +137,9 @@ static u8 pmic8xxx_col_state(struct pmic8xxx_kp *kp, u8 col) static int pmic8xxx_chk_sync_read(struct pmic8xxx_kp *kp) { int rc; - u8 scan_val; + unsigned int scan_val; - rc = pmic8xxx_kp_read_u8(kp, &scan_val, KEYP_SCAN); + rc = regmap_read(kp->regmap, KEYP_SCAN, &scan_val); if (rc < 0) { dev_err(kp->dev, "Error reading KEYP_SCAN reg, rc=%d\n", rc); return rc; @@ -171,7 +147,7 @@ static int pmic8xxx_chk_sync_read(struct pmic8xxx_kp *kp) scan_val |= 0x1; - rc = pmic8xxx_kp_write_u8(kp, scan_val, KEYP_SCAN); + rc = regmap_write(kp->regmap, KEYP_SCAN, scan_val); if (rc < 0) { dev_err(kp->dev, "Error writing KEYP_SCAN reg, rc=%d\n", rc); return rc; @@ -187,31 +163,29 @@ static int pmic8xxx_kp_read_data(struct pmic8xxx_kp *kp, u16 *state, u16 data_reg, int read_rows) { int rc, row; - u8 new_data[PM8XXX_MAX_ROWS]; - - rc = pmic8xxx_kp_read(kp, new_data, data_reg, read_rows); - if (rc) - return rc; + unsigned int val; - for (row = 0; row < kp->pdata->num_rows; row++) { - dev_dbg(kp->dev, "new_data[%d] = %d\n", row, - new_data[row]); - state[row] = pmic8xxx_col_state(kp, new_data[row]); + for (row = 0; row < read_rows; row++) { + rc = regmap_read(kp->regmap, data_reg, &val); + if (rc) + return rc; + dev_dbg(kp->dev, "%d = %d\n", row, val); + state[row] = pmic8xxx_col_state(kp, val); } - return rc; + return 0; } static int pmic8xxx_kp_read_matrix(struct pmic8xxx_kp *kp, u16 *new_state, u16 *old_state) { int rc, read_rows; - u8 scan_val; + unsigned int scan_val; - if (kp->pdata->num_rows < PM8XXX_MIN_ROWS) + if (kp->num_rows < PM8XXX_MIN_ROWS) read_rows = PM8XXX_MIN_ROWS; else - read_rows = kp->pdata->num_rows; + read_rows = kp->num_rows; pmic8xxx_chk_sync_read(kp); @@ -236,14 +210,14 @@ static int pmic8xxx_kp_read_matrix(struct pmic8xxx_kp *kp, u16 *new_state, /* 4 * 32KHz clocks */ udelay((4 * DIV_ROUND_UP(USEC_PER_SEC, KEYP_CLOCK_FREQ)) + 1); - rc = pmic8xxx_kp_read_u8(kp, &scan_val, KEYP_SCAN); + rc = regmap_read(kp->regmap, KEYP_SCAN, &scan_val); if (rc < 0) { dev_err(kp->dev, "Error reading KEYP_SCAN reg, rc=%d\n", rc); return rc; } scan_val &= 0xFE; - rc = pmic8xxx_kp_write_u8(kp, scan_val, KEYP_SCAN); + rc = regmap_write(kp->regmap, KEYP_SCAN, scan_val); if (rc < 0) dev_err(kp->dev, "Error writing KEYP_SCAN reg, rc=%d\n", rc); @@ -255,13 +229,13 @@ static void __pmic8xxx_kp_scan_matrix(struct pmic8xxx_kp *kp, u16 *new_state, { int row, col, code; - for (row = 0; row < kp->pdata->num_rows; row++) { + for (row = 0; row < kp->num_rows; row++) { int bits_changed = new_state[row] ^ old_state[row]; if (!bits_changed) continue; - for (col = 0; col < kp->pdata->num_cols; col++) { + for (col = 0; col < kp->num_cols; col++) { if (!(bits_changed & (1 << col))) continue; @@ -287,9 +261,9 @@ static bool pmic8xxx_detect_ghost_keys(struct pmic8xxx_kp *kp, u16 *new_state) u16 check, row_state; check = 0; - for (row = 0; row < kp->pdata->num_rows; row++) { + for (row = 0; row < kp->num_rows; row++) { row_state = (~new_state[row]) & - ((1 << kp->pdata->num_cols) - 1); + ((1 << kp->num_cols) - 1); if (hweight16(row_state) > 1) { if (found_first == -1) @@ -379,10 +353,10 @@ static irqreturn_t pmic8xxx_kp_stuck_irq(int irq, void *data) static irqreturn_t pmic8xxx_kp_irq(int irq, void *data) { struct pmic8xxx_kp *kp = data; - u8 ctrl_val, events; + unsigned int ctrl_val, events; int rc; - rc = pmic8xxx_kp_read(kp, &ctrl_val, KEYP_CTRL, 1); + rc = regmap_read(kp->regmap, KEYP_CTRL, &ctrl_val); if (rc < 0) { dev_err(kp->dev, "failed to read keyp_ctrl register\n"); return IRQ_HANDLED; @@ -397,8 +371,13 @@ static irqreturn_t pmic8xxx_kp_irq(int irq, void *data) return IRQ_HANDLED; } -static int pmic8xxx_kpd_init(struct pmic8xxx_kp *kp) +static int pmic8xxx_kpd_init(struct pmic8xxx_kp *kp, + struct platform_device *pdev) { + const struct device_node *of_node = pdev->dev.of_node; + unsigned int scan_delay_ms; + unsigned int row_hold_ns; + unsigned int debounce_ms; int bits, rc, cycles; u8 scan_val = 0, ctrl_val = 0; static const u8 row_bits[] = { @@ -406,40 +385,69 @@ static int pmic8xxx_kpd_init(struct pmic8xxx_kp *kp) }; /* Find column bits */ - if (kp->pdata->num_cols < KEYP_CTRL_SCAN_COLS_MIN) + if (kp->num_cols < KEYP_CTRL_SCAN_COLS_MIN) bits = 0; else - bits = kp->pdata->num_cols - KEYP_CTRL_SCAN_COLS_MIN; + bits = kp->num_cols - KEYP_CTRL_SCAN_COLS_MIN; ctrl_val = (bits & KEYP_CTRL_SCAN_COLS_BITS) << KEYP_CTRL_SCAN_COLS_SHIFT; /* Find row bits */ - if (kp->pdata->num_rows < KEYP_CTRL_SCAN_ROWS_MIN) + if (kp->num_rows < KEYP_CTRL_SCAN_ROWS_MIN) bits = 0; else - bits = row_bits[kp->pdata->num_rows - KEYP_CTRL_SCAN_ROWS_MIN]; + bits = row_bits[kp->num_rows - KEYP_CTRL_SCAN_ROWS_MIN]; ctrl_val |= (bits << KEYP_CTRL_SCAN_ROWS_SHIFT); - rc = pmic8xxx_kp_write_u8(kp, ctrl_val, KEYP_CTRL); + rc = regmap_write(kp->regmap, KEYP_CTRL, ctrl_val); if (rc < 0) { dev_err(kp->dev, "Error writing KEYP_CTRL reg, rc=%d\n", rc); return rc; } - bits = (kp->pdata->debounce_ms / 5) - 1; + if (of_property_read_u32(of_node, "scan-delay", &scan_delay_ms)) + scan_delay_ms = MIN_SCAN_DELAY; + + if (scan_delay_ms > MAX_SCAN_DELAY || scan_delay_ms < MIN_SCAN_DELAY || + !is_power_of_2(scan_delay_ms)) { + dev_err(&pdev->dev, "invalid keypad scan time supplied\n"); + return -EINVAL; + } + + if (of_property_read_u32(of_node, "row-hold", &row_hold_ns)) + row_hold_ns = MIN_ROW_HOLD_DELAY; + + if (row_hold_ns > MAX_ROW_HOLD_DELAY || + row_hold_ns < MIN_ROW_HOLD_DELAY || + ((row_hold_ns % MIN_ROW_HOLD_DELAY) != 0)) { + dev_err(&pdev->dev, "invalid keypad row hold time supplied\n"); + return -EINVAL; + } + + if (of_property_read_u32(of_node, "debounce", &debounce_ms)) + debounce_ms = MIN_DEBOUNCE_TIME; + + if (((debounce_ms % 5) != 0) || + debounce_ms > MAX_DEBOUNCE_TIME || + debounce_ms < MIN_DEBOUNCE_TIME) { + dev_err(&pdev->dev, "invalid debounce time supplied\n"); + return -EINVAL; + } + + bits = (debounce_ms / 5) - 1; scan_val |= (bits << KEYP_SCAN_DBOUNCE_SHIFT); - bits = fls(kp->pdata->scan_delay_ms) - 1; + bits = fls(scan_delay_ms) - 1; scan_val |= (bits << KEYP_SCAN_PAUSE_SHIFT); /* Row hold time is a multiple of 32KHz cycles. */ - cycles = (kp->pdata->row_hold_ns * KEYP_CLOCK_FREQ) / NSEC_PER_SEC; + cycles = (row_hold_ns * KEYP_CLOCK_FREQ) / NSEC_PER_SEC; scan_val |= (cycles << KEYP_SCAN_ROW_HOLD_SHIFT); - rc = pmic8xxx_kp_write_u8(kp, scan_val, KEYP_SCAN); + rc = regmap_write(kp->regmap, KEYP_SCAN, scan_val); if (rc) dev_err(kp->dev, "Error writing KEYP_SCAN reg, rc=%d\n", rc); @@ -447,34 +455,13 @@ static int pmic8xxx_kpd_init(struct pmic8xxx_kp *kp) } -static int pmic8xxx_kp_config_gpio(int gpio_start, int num_gpios, - struct pmic8xxx_kp *kp, struct pm_gpio *gpio_config) -{ - int rc, i; - - if (gpio_start < 0 || num_gpios < 0) - return -EINVAL; - - for (i = 0; i < num_gpios; i++) { - rc = pm8xxx_gpio_config(gpio_start + i, gpio_config); - if (rc) { - dev_err(kp->dev, "%s: FAIL pm8xxx_gpio_config():" - "for PM GPIO [%d] rc=%d.\n", - __func__, gpio_start + i, rc); - return rc; - } - } - - return 0; -} - static int pmic8xxx_kp_enable(struct pmic8xxx_kp *kp) { int rc; kp->ctrl_reg |= KEYP_CTRL_KEYP_EN; - rc = pmic8xxx_kp_write_u8(kp, kp->ctrl_reg, KEYP_CTRL); + rc = regmap_write(kp->regmap, KEYP_CTRL, kp->ctrl_reg); if (rc < 0) dev_err(kp->dev, "Error writing KEYP_CTRL reg, rc=%d\n", rc); @@ -487,7 +474,7 @@ static int pmic8xxx_kp_disable(struct pmic8xxx_kp *kp) kp->ctrl_reg &= ~KEYP_CTRL_KEYP_EN; - rc = pmic8xxx_kp_write_u8(kp, kp->ctrl_reg, KEYP_CTRL); + rc = regmap_write(kp->regmap, KEYP_CTRL, kp->ctrl_reg); if (rc < 0) return rc; @@ -520,106 +507,62 @@ static void pmic8xxx_kp_close(struct input_dev *dev) */ static int pmic8xxx_kp_probe(struct platform_device *pdev) { - const struct pm8xxx_keypad_platform_data *pdata = - dev_get_platdata(&pdev->dev); - const struct matrix_keymap_data *keymap_data; + unsigned int rows, cols; + bool repeat; + bool wakeup; struct pmic8xxx_kp *kp; int rc; - u8 ctrl_val; - - struct pm_gpio kypd_drv = { - .direction = PM_GPIO_DIR_OUT, - .output_buffer = PM_GPIO_OUT_BUF_OPEN_DRAIN, - .output_value = 0, - .pull = PM_GPIO_PULL_NO, - .vin_sel = PM_GPIO_VIN_S3, - .out_strength = PM_GPIO_STRENGTH_LOW, - .function = PM_GPIO_FUNC_1, - .inv_int_pol = 1, - }; - - struct pm_gpio kypd_sns = { - .direction = PM_GPIO_DIR_IN, - .pull = PM_GPIO_PULL_UP_31P5, - .vin_sel = PM_GPIO_VIN_S3, - .out_strength = PM_GPIO_STRENGTH_NO, - .function = PM_GPIO_FUNC_NORMAL, - .inv_int_pol = 1, - }; + unsigned int ctrl_val; + rc = matrix_keypad_parse_of_params(&pdev->dev, &rows, &cols); + if (rc) + return rc; - if (!pdata || !pdata->num_cols || !pdata->num_rows || - pdata->num_cols > PM8XXX_MAX_COLS || - pdata->num_rows > PM8XXX_MAX_ROWS || - pdata->num_cols < PM8XXX_MIN_COLS) { + if (cols > PM8XXX_MAX_COLS || rows > PM8XXX_MAX_ROWS || + cols < PM8XXX_MIN_COLS) { dev_err(&pdev->dev, "invalid platform data\n"); return -EINVAL; } - if (!pdata->scan_delay_ms || - pdata->scan_delay_ms > MAX_SCAN_DELAY || - pdata->scan_delay_ms < MIN_SCAN_DELAY || - !is_power_of_2(pdata->scan_delay_ms)) { - dev_err(&pdev->dev, "invalid keypad scan time supplied\n"); - return -EINVAL; - } - - if (!pdata->row_hold_ns || - pdata->row_hold_ns > MAX_ROW_HOLD_DELAY || - pdata->row_hold_ns < MIN_ROW_HOLD_DELAY || - ((pdata->row_hold_ns % MIN_ROW_HOLD_DELAY) != 0)) { - dev_err(&pdev->dev, "invalid keypad row hold time supplied\n"); - return -EINVAL; - } - - if (!pdata->debounce_ms || - ((pdata->debounce_ms % 5) != 0) || - pdata->debounce_ms > MAX_DEBOUNCE_TIME || - pdata->debounce_ms < MIN_DEBOUNCE_TIME) { - dev_err(&pdev->dev, "invalid debounce time supplied\n"); - return -EINVAL; - } - - keymap_data = pdata->keymap_data; - if (!keymap_data) { - dev_err(&pdev->dev, "no keymap data supplied\n"); - return -EINVAL; - } + repeat = !of_property_read_bool(pdev->dev.of_node, + "linux,input-no-autorepeat"); + wakeup = of_property_read_bool(pdev->dev.of_node, + "linux,keypad-wakeup"); - kp = kzalloc(sizeof(*kp), GFP_KERNEL); + kp = devm_kzalloc(&pdev->dev, sizeof(*kp), GFP_KERNEL); if (!kp) return -ENOMEM; + kp->regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!kp->regmap) + return -ENODEV; + platform_set_drvdata(pdev, kp); - kp->pdata = pdata; + kp->num_rows = rows; + kp->num_cols = cols; kp->dev = &pdev->dev; - kp->input = input_allocate_device(); + kp->input = devm_input_allocate_device(&pdev->dev); if (!kp->input) { dev_err(&pdev->dev, "unable to allocate input device\n"); - rc = -ENOMEM; - goto err_alloc_device; + return -ENOMEM; } kp->key_sense_irq = platform_get_irq(pdev, 0); if (kp->key_sense_irq < 0) { dev_err(&pdev->dev, "unable to get keypad sense irq\n"); - rc = -ENXIO; - goto err_get_irq; + return kp->key_sense_irq; } kp->key_stuck_irq = platform_get_irq(pdev, 1); if (kp->key_stuck_irq < 0) { dev_err(&pdev->dev, "unable to get keypad stuck irq\n"); - rc = -ENXIO; - goto err_get_irq; + return kp->key_stuck_irq; } - kp->input->name = pdata->input_name ? : "PMIC8XXX keypad"; - kp->input->phys = pdata->input_phys_device ? : "pmic8xxx_keypad/input0"; - - kp->input->dev.parent = &pdev->dev; + kp->input->name = "PMIC8XXX keypad"; + kp->input->phys = "pmic8xxx_keypad/input0"; kp->input->id.bustype = BUS_I2C; kp->input->id.version = 0x0001; @@ -629,15 +572,15 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev) kp->input->open = pmic8xxx_kp_open; kp->input->close = pmic8xxx_kp_close; - rc = matrix_keypad_build_keymap(keymap_data, NULL, + rc = matrix_keypad_build_keymap(NULL, NULL, PM8XXX_MAX_ROWS, PM8XXX_MAX_COLS, kp->keycodes, kp->input); if (rc) { dev_err(&pdev->dev, "failed to build keymap\n"); - goto err_get_irq; + return rc; } - if (pdata->rep) + if (repeat) __set_bit(EV_REP, kp->input->evbit); input_set_capability(kp->input, EV_MSC, MSC_SCAN); @@ -647,44 +590,32 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev) memset(kp->keystate, 0xff, sizeof(kp->keystate)); memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate)); - rc = pmic8xxx_kpd_init(kp); + rc = pmic8xxx_kpd_init(kp, pdev); if (rc < 0) { dev_err(&pdev->dev, "unable to initialize keypad controller\n"); - goto err_get_irq; - } - - rc = pmic8xxx_kp_config_gpio(pdata->cols_gpio_start, - pdata->num_cols, kp, &kypd_sns); - if (rc < 0) { - dev_err(&pdev->dev, "unable to configure keypad sense lines\n"); - goto err_gpio_config; - } - - rc = pmic8xxx_kp_config_gpio(pdata->rows_gpio_start, - pdata->num_rows, kp, &kypd_drv); - if (rc < 0) { - dev_err(&pdev->dev, "unable to configure keypad drive lines\n"); - goto err_gpio_config; + return rc; } - rc = request_any_context_irq(kp->key_sense_irq, pmic8xxx_kp_irq, - IRQF_TRIGGER_RISING, "pmic-keypad", kp); + rc = devm_request_any_context_irq(&pdev->dev, kp->key_sense_irq, + pmic8xxx_kp_irq, IRQF_TRIGGER_RISING, "pmic-keypad", + kp); if (rc < 0) { dev_err(&pdev->dev, "failed to request keypad sense irq\n"); - goto err_get_irq; + return rc; } - rc = request_any_context_irq(kp->key_stuck_irq, pmic8xxx_kp_stuck_irq, - IRQF_TRIGGER_RISING, "pmic-keypad-stuck", kp); + rc = devm_request_any_context_irq(&pdev->dev, kp->key_stuck_irq, + pmic8xxx_kp_stuck_irq, IRQF_TRIGGER_RISING, + "pmic-keypad-stuck", kp); if (rc < 0) { dev_err(&pdev->dev, "failed to request keypad stuck irq\n"); - goto err_req_stuck_irq; + return rc; } - rc = pmic8xxx_kp_read_u8(kp, &ctrl_val, KEYP_CTRL); + rc = regmap_read(kp->regmap, KEYP_CTRL, &ctrl_val); if (rc < 0) { dev_err(&pdev->dev, "failed to read KEYP_CTRL register\n"); - goto err_pmic_reg_read; + return rc; } kp->ctrl_reg = ctrl_val; @@ -692,34 +623,10 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev) rc = input_register_device(kp->input); if (rc < 0) { dev_err(&pdev->dev, "unable to register keypad input device\n"); - goto err_pmic_reg_read; + return rc; } - device_init_wakeup(&pdev->dev, pdata->wakeup); - - return |