From: Gireesh Hiremath <[email protected]>
add support for keypad driver running on Bosch Guardian
Dtect board using TI-am335x cpu. Driver implementation
is based on matrix_keypad.c
Signed-off-by: Gireesh Hiremath <[email protected]>
---
drivers/input/keyboard/Kconfig | 10 +
drivers/input/keyboard/Makefile | 1 +
drivers/input/keyboard/mt_matrix_keypad.c | 741 ++++++++++++++++++++++
include/linux/input/mt_matrix_keypad.h | 63 ++
4 files changed, 815 insertions(+)
create mode 100644 drivers/input/keyboard/mt_matrix_keypad.c
create mode 100644 include/linux/input/mt_matrix_keypad.h
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 4ea79db8f134..a55ee8656194 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -303,6 +303,16 @@ config KEYBOARD_MATRIX
To compile this driver as a module, choose M here: the
module will be called matrix_keypad.
+config KEYBOARD_MT_MATRIX
+ tristate "GPIO driven MT matrix keypad support"
+ depends on GPIOLIB || COMPILE_TEST
+ help
+ This driver enable support for GPIO driven
+ mt matrix keypad.
+
+ To compile this driver as a module, choose M here: the
+ module will be called mt_matrix_keypad.
+
config KEYBOARD_HIL_OLD
tristate "HP HIL keyboard support (simple driver)"
depends on GSC || HP300
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 721936e90290..c7686d338b5d 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o
obj-$(CONFIG_KEYBOARD_LPC32XX) += lpc32xx-keys.o
obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o
obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o
+obj-$(CONFIG_KEYBOARD_MT_MATRIX) += mt_matrix_keypad.o
obj-$(CONFIG_KEYBOARD_MAX7359) += max7359_keypad.o
obj-$(CONFIG_KEYBOARD_MCS) += mcs_touchkey.o
obj-$(CONFIG_KEYBOARD_MPR121) += mpr121_touchkey.o
diff --git a/drivers/input/keyboard/mt_matrix_keypad.c b/drivers/input/keyboard/mt_matrix_keypad.c
new file mode 100644
index 000000000000..9310faf8b237
--- /dev/null
+++ b/drivers/input/keyboard/mt_matrix_keypad.c
@@ -0,0 +1,741 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * GPIO driven mt matrix keyboard driver
+ *
+ * Copyright (c) 2008 Marek Vasut <[email protected]>
+ * Copyright (c) 2017 vinay <[email protected]>
+ *
+ * Based on matrix_keypad.c
+ *
+ */
+
+#include <linux/stddef.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/input/mt_matrix_keypad.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
+#include <linux/pinctrl/consumer.h>
+
+#define MODULE_NAME "mt-matrix-keypad"
+
+struct mt_matrix_keypad {
+ struct mt_matrix_keypad_platform_data *pdata;
+ struct input_dev *input_dev;
+
+ DECLARE_BITMAP(disabled_gpios, MATRIX_MAX_ROWS);
+
+ struct delayed_work work;
+ spinlock_t lock;
+ bool scan_pending;
+ bool stopped;
+ bool gpio_all_disabled;
+};
+
+static bool
+get_gpio_line_value(const struct mt_matrix_keypad_platform_data *pdata,
+ int row);
+static void
+activate_line_driving(const struct mt_matrix_keypad_platform_data *pdata,
+ int line, bool on);
+
+void init_phase(struct mt_matrix_keypad_platform_data *pdata)
+{
+ pdata->phase_state.phase_prepare = -1;
+ pdata->phase_state.phase_start = 0;
+ pdata->phase_state.phase_update_button = pdata->num_line_gpios;
+}
+
+void button_init(struct button *btn, bool btn_hw_state, int key)
+{
+ btn->state.boPrevious = btn_hw_state;
+ btn->state.boCurrentStateOfHw = btn_hw_state;
+ btn->state.boCurrentStateOfSw = false;
+ btn->state.boCurrent = btn_hw_state;
+ btn->state.boEnabled = true;
+ btn->state.boStateAtInit = btn_hw_state;
+ btn->event.ui8Register = 0;
+ btn->key = key;
+}
+
+const struct button_states get_button_state(struct button *btn)
+{
+ return btn->state;
+}
+
+union typeEvent get_and_clear_events(struct button *btn)
+{
+ union typeEvent beTemp = btn->event;
+
+ btn->event.ui8Register = 0;
+
+ return beTemp;
+}
+
+uint8_t get_btn_index(struct mt_matrix_keypad_platform_data *pdata, int btn_key)
+{
+ uint8_t i;
+
+ for (i = 0; i < pdata->num_of_button; i++) {
+ if (pdata->button_array[i].key == btn_key)
+ break;
+ }
+ return i;
+}
+
+void set_btn_state_by_hw(struct button *btn, bool boButtonState)
+{
+ btn->state.boCurrentStateOfHw = boButtonState;
+}
+
+bool check_button_changes(struct button *btn)
+{
+ btn->state.boPrevious = btn->state.boCurrent;
+ btn->state.boCurrent =
+ btn->state.boCurrentStateOfHw || btn->state.boCurrentStateOfSw;
+
+ /* Check if Button is pressed */
+ if ((btn->state.boPrevious == false) &&
+ (btn->state.boCurrent == true)) {
+ btn->event.status.boPressed = true;
+ }
+
+ /* Check if Button is released */
+ else if ((btn->state.boPrevious == true) &&
+ (btn->state.boCurrent == false)) {
+ btn->event.status.boReleased = true;
+ }
+
+ if (btn->event.ui8Register != 0)
+ btn->event.status.boGlobalChanged = true;
+
+ return btn->event.status.boGlobalChanged;
+}
+
+const struct button_states
+get_btn_id_state(const struct mt_matrix_keypad_platform_data *pdata,
+ int btn_index)
+{
+ if (btn_index < pdata->num_of_button)
+ return get_button_state(&pdata->button_array[btn_index]);
+ else
+ return get_button_state(&pdata->button_array[0]);
+}
+
+union typeEvent
+get_and_clear_btn_events(const struct mt_matrix_keypad_platform_data *pdata,
+ int btn_index)
+{
+ if (btn_index < pdata->num_of_button)
+ return get_and_clear_events(&pdata->button_array[btn_index]);
+ else
+ return get_and_clear_events(&pdata->button_array[0]);
+}
+
+void button_hdl_init(struct mt_matrix_keypad_platform_data *pdata)
+{
+ int row, col, index;
+ int i;
+
+ pdata->scan_phase = pdata->phase_state.phase_prepare;
+ pdata->intialize_buttons = true;
+
+ /* Init Button Objects, will be reinited once states are captured */
+ i = 0;
+ for (row = 1; row < pdata->num_line_gpios; row++)
+ for (col = 0; col < row; col++) {
+ index = (row * pdata->num_line_gpios) + col;
+ if (pdata->button_matrix[index] !=
+ pdata->button_matrix[0]) {
+ if (i < pdata->num_of_button) {
+ button_init(
+ &pdata->button_array[i], false,
+ pdata->button_matrix[index]);
+ i++;
+ }
+ }
+ }
+
+ pr_debug("[%s]: %s Done\n", MODULE_NAME, __func__);
+}
+
+bool on_button_event(const struct mt_matrix_keypad_platform_data *pdata,
+ int btn_index, union typeEvent btn_event,
+ struct input_dev *input_dev)
+{
+ bool any_btn_served = true;
+ unsigned int key_code = 0;
+ int key_value = 0;
+
+ key_code = pdata->button_array[btn_index].key;
+
+ if (btn_event.status.boPressed) {
+ key_value = 1;
+ pr_debug("[%s]:%d Pressed\n", MODULE_NAME, key_code);
+ }
+
+ if (btn_event.status.boReleased) {
+ key_value = 0;
+ pr_debug("[%s]:%d Released\n", MODULE_NAME, key_code);
+ }
+
+ input_report_key(input_dev, key_code, key_value);
+ input_sync(input_dev);
+ return any_btn_served;
+}
+
+void process_button_events(const struct mt_matrix_keypad_platform_data *pdata,
+ struct input_dev *input_dev)
+{
+ int btn_index;
+ bool any_btn_served = false;
+
+ for (btn_index = 0; btn_index < pdata->num_of_button; btn_index++) {
+ const union typeEvent beEvent =
+ get_and_clear_btn_events(pdata, (int)btn_index);
+
+ if (beEvent.status.boGlobalChanged) {
+ const struct button_states bsState =
+ get_btn_id_state(pdata, (int)btn_index);
+
+ if (bsState.boEnabled) {
+ any_btn_served |=
+ on_button_event(pdata, (int)btn_index,
+ beEvent, input_dev);
+ }
+ }
+ }
+}
+
+void update_buttons(struct mt_matrix_keypad_platform_data *pdata,
+ struct input_dev *input_dev)
+{
+ if (pdata->scan_phase == pdata->phase_state.phase_prepare) {
+ pdata->scan_phase = pdata->phase_state.phase_start;
+ activate_line_driving(pdata, (int)pdata->scan_phase, true);
+ } else if (pdata->scan_phase ==
+ pdata->phase_state.phase_update_button) {
+ bool btn_changes_occured = false;
+ int btn_index;
+
+ if (pdata->intialize_buttons) {
+ int i;
+
+ pdata->intialize_buttons = false;
+
+ for (i = 0; i < pdata->num_of_button; i++) {
+ const bool btn_curr_hw_state =
+ get_button_state(
+ &pdata->button_array[i])
+ .boCurrentStateOfHw;
+ button_init(&pdata->button_array[i],
+ btn_curr_hw_state,
+ pdata->button_array[i].key);
+ }
+ }
+
+ for (btn_index = 0; btn_index < pdata->num_of_button;
+ btn_index++) {
+ btn_changes_occured |= check_button_changes(
+ &pdata->button_array[btn_index]);
+ }
+
+ if (btn_changes_occured)
+ process_button_events(pdata, input_dev);
+
+ pdata->scan_phase = pdata->phase_state.phase_start;
+ } else {
+ uint8_t *btn_keylines;
+ uint8_t number_of_buttons_pressed = 0;
+ uint8_t btn_index;
+ uint8_t btn_key;
+ uint16_t index;
+ int i;
+
+ btn_keylines = kcalloc(pdata->num_line_gpios, sizeof(uint8_t),
+ GFP_KERNEL);
+ for (i = 0; i < pdata->num_line_gpios; i++) {
+ index = (pdata->scan_phase * pdata->num_line_gpios) + i;
+ btn_key = pdata->button_matrix[index];
+ btn_keylines[i] = false;
+
+ if ((btn_key != pdata->button_matrix[0]) &&
+ (get_gpio_line_value(pdata, (int)i) != false)) {
+ btn_keylines[i] = true;
+ number_of_buttons_pressed++;
+ }
+ }
+ if (number_of_buttons_pressed < 2) {
+ for (i = 0; i < pdata->num_line_gpios; i++) {
+ index = (pdata->scan_phase *
+ pdata->num_line_gpios) +
+ i;
+ btn_key = pdata->button_matrix[index];
+ if (btn_key != pdata->button_matrix[0]) {
+ btn_index =
+ get_btn_index(pdata, btn_key);
+ set_btn_state_by_hw(
+ &pdata->button_array[btn_index],
+ btn_keylines[i]);
+ }
+ }
+ }
+
+ kfree(btn_keylines);
+ activate_line_driving(pdata, (int)pdata->scan_phase, false);
+ pdata->scan_phase++;
+ activate_line_driving(
+ pdata, (int)(pdata->scan_phase % pdata->num_line_gpios),
+ true);
+ }
+}
+
+/*
+ * NOTE: normally the GPIO has to be put into HiZ when de-activated to cause
+ * minmal side effect when scanning other columns, here it is configured to
+ * be input, and it should work on most platforms.
+ */
+static void
+__activate_line_driving(const struct mt_matrix_keypad_platform_data *pdata,
+ int line, bool on)
+{
+ bool level_on = pdata->active_low;
+
+ if (on)
+ gpio_direction_output(pdata->line_gpios[line], level_on);
+ else
+ gpio_direction_input(pdata->line_gpios[line]);
+}
+
+static void
+activate_line_driving(const struct mt_matrix_keypad_platform_data *pdata,
+ int line, bool on)
+{
+ __activate_line_driving(pdata, line, on);
+
+ if (on && pdata->col_scan_delay_us)
+ udelay(pdata->col_scan_delay_us);
+}
+
+static bool
+get_gpio_line_value(const struct mt_matrix_keypad_platform_data *pdata, int row)
+{
+ return gpio_get_value(pdata->line_gpios[row]) ? pdata->active_low :
+ !pdata->active_low;
+}
+
+/*
+ * This gets the keys from keyboard and reports it to input subsystem
+ */
+static void mt_matrix_keypad_scan(struct work_struct *work)
+{
+ struct mt_matrix_keypad *keypad =
+ container_of(work, struct mt_matrix_keypad, work.work);
+ struct input_dev *input_dev = keypad->input_dev;
+ struct mt_matrix_keypad_platform_data *pdata = keypad->pdata;
+
+ if (keypad->stopped == false) {
+ update_buttons(pdata, input_dev);
+ schedule_delayed_work(
+ &keypad->work,
+ msecs_to_jiffies(keypad->pdata->debounce_ms));
+ }
+}
+
+static int mt_matrix_keypad_start(struct input_dev *dev)
+{
+ struct mt_matrix_keypad *keypad = input_get_drvdata(dev);
+
+ keypad->stopped = false;
+ /*
+ * memory access initiated before the memory barrier
+ * will be complete before passing the barrier
+ */
+ mb();
+
+ /*
+ * Schedule an immediate key scan to capture current key state;
+ * columns will be activated and IRQs be enabled after the scan.
+ */
+ schedule_delayed_work(&keypad->work, 0);
+
+ return 0;
+}
+
+static void mt_matrix_keypad_stop(struct input_dev *dev)
+{
+ struct mt_matrix_keypad *keypad = input_get_drvdata(dev);
+
+ keypad->stopped = true;
+ /*
+ * memory access initiated before the memory barrier
+ * will be complete before passing the barrier
+ */
+ mb();
+ cancel_delayed_work_sync(&keypad->work);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static void mt_matrix_keypad_enable_wakeup(struct mt_matrix_keypad *keypad)
+{
+ const struct mt_matrix_keypad_platform_data *pdata = keypad->pdata;
+ unsigned int gpio;
+ int i;
+
+ if (pdata->clustered_irq > 0) {
+ if (enable_irq_wake(pdata->clustered_irq) == 0)
+ keypad->gpio_all_disabled = true;
+ } else {
+ for (i = 0; i < pdata->num_line_gpios; i++) {
+ if (!test_bit(i, keypad->disabled_gpios)) {
+ gpio = pdata->line_gpios[i];
+
+ if (enable_irq_wake(gpio_to_irq(gpio)) == 0)
+ __set_bit(i, keypad->disabled_gpios);
+ }
+ }
+ }
+}
+
+static void mt_matrix_keypad_disable_wakeup(struct mt_matrix_keypad *keypad)
+{
+ const struct mt_matrix_keypad_platform_data *pdata = keypad->pdata;
+ unsigned int gpio;
+ int i;
+
+ if (pdata->clustered_irq > 0) {
+ if (keypad->gpio_all_disabled) {
+ disable_irq_wake(pdata->clustered_irq);
+ keypad->gpio_all_disabled = false;
+ }
+ } else {
+ for (i = 0; i < pdata->num_line_gpios; i++) {
+ if (test_and_clear_bit(i, keypad->disabled_gpios)) {
+ gpio = pdata->line_gpios[i];
+ disable_irq_wake(gpio_to_irq(gpio));
+ }
+ }
+ }
+}
+
+static int mt_matrix_keypad_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct mt_matrix_keypad *keypad = platform_get_drvdata(pdev);
+
+ mt_matrix_keypad_stop(keypad->input_dev);
+
+ if (device_may_wakeup(&pdev->dev))
+ mt_matrix_keypad_enable_wakeup(keypad);
+
+ pinctrl_pm_select_sleep_state(dev);
+
+ return 0;
+}
+
+static int mt_matrix_keypad_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct mt_matrix_keypad *keypad = platform_get_drvdata(pdev);
+
+ if (device_may_wakeup(&pdev->dev))
+ mt_matrix_keypad_disable_wakeup(keypad);
+
+ pinctrl_pm_select_default_state(dev);
+
+ mt_matrix_keypad_start(keypad->input_dev);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(mt_matrix_keypad_pm_ops, mt_matrix_keypad_suspend,
+ mt_matrix_keypad_resume);
+
+static int mt_matrix_keypad_init_gpio(struct platform_device *pdev,
+ struct mt_matrix_keypad *keypad)
+{
+ const struct mt_matrix_keypad_platform_data *pdata = keypad->pdata;
+ int i, err;
+
+ for (i = 0; i < pdata->num_line_gpios; i++) {
+ err = gpio_request(pdata->line_gpios[i], "mt_kbd_row");
+ if (err) {
+ dev_err(&pdev->dev,
+ "failed to request GPIO%d for ROW%d\n",
+ pdata->line_gpios[i], i);
+ goto err_free_rows;
+ }
+
+ gpio_direction_input(pdata->line_gpios[i]);
+ }
+
+ return 0;
+
+err_free_rows:
+ while (--i >= 0)
+ gpio_free(pdata->line_gpios[i]);
+
+ i = pdata->num_line_gpios;
+ return err;
+}
+
+static void mt_matrix_keypad_free_gpio(struct mt_matrix_keypad *keypad)
+{
+ const struct mt_matrix_keypad_platform_data *pdata = keypad->pdata;
+ int i;
+
+ for (i = 0; i < pdata->num_line_gpios; i++)
+ gpio_free(pdata->line_gpios[i]);
+}
+
+#ifdef CONFIG_OF
+static struct mt_matrix_keypad_platform_data *
+mt_matrix_keypad_parse_dt(struct device *dev)
+{
+ struct mt_matrix_keypad_platform_data *pdata = NULL;
+ struct device_node *np = dev->of_node;
+ unsigned int *gpios;
+ struct button *button_array;
+ int8_t *button_matrix;
+ uint16_t keycode;
+ uint32_t *ptr;
+ int keymap;
+ int i;
+
+ if (!np) {
+ dev_err(dev, "device lacks DT data\n");
+ return ERR_PTR(-ENODEV);
+ }
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return ERR_PTR(-ENOMEM);
+
+ pdata->num_line_gpios = of_gpio_named_count(np, "line-gpios");
+ if (pdata->num_line_gpios <= 0) {
+ dev_err(dev, "number of gpio line not specified\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_get_property(np, "linux,no-autorepeat", NULL))
+ pdata->no_autorepeat = true;
+
+ pdata->wakeup = of_property_read_bool(np, "wakeup-source") ||
+ of_property_read_bool(np, "linux,wakeup"); /* legacy */
+
+ if (of_get_property(np, "gpio-activelow", NULL))
+ pdata->active_low = true;
+
+ of_property_read_u32(np, "debounce-delay-ms", &pdata->debounce_ms);
+ of_property_read_u32(np, "col-scan-delay-us",
+ &pdata->col_scan_delay_us);
+ of_property_read_u32(np, "number-of-button", &pdata->num_of_button);
+ if (pdata->num_of_button <= 0) {
+ dev_err(dev, "number of button not specified\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ button_array =
+ devm_kzalloc(dev,
+ sizeof(struct button) * (pdata->num_of_button),
+ GFP_KERNEL);
+ if (!button_array) {
+ dev_err(dev, "could not allocate memory for button array\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ pdata->button_array = button_array;
+
+ gpios = devm_kzalloc(dev,
+ sizeof(unsigned int) * (pdata->num_line_gpios),
+ GFP_KERNEL);
+ if (!gpios) {
+ dev_err(dev, "could not allocate memory for gpios\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ for (i = 0; i < pdata->num_line_gpios; i++)
+ gpios[i] = of_get_named_gpio(np, "line-gpios", i);
+
+ pdata->line_gpios = gpios;
+
+ keymap = device_property_count_u32(dev, "linux,keymap");
+ if (keymap <= 0 ||
+ keymap > (pdata->num_line_gpios * pdata->num_line_gpios)) {
+ dev_err(dev, "linux,keymap property count is more");
+ return ERR_PTR(-ENXIO);
+ }
+
+ ptr = kcalloc(keymap, sizeof(uint32_t), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ if (device_property_read_u32_array(dev, "linux,keymap", ptr, keymap)) {
+ dev_err(dev, "problem parsing keymap property\n");
+ kfree(ptr);
+ return ERR_PTR(-EINVAL);
+ }
+
+ button_matrix =
+ devm_kzalloc(dev, (keymap * sizeof(int8_t)), GFP_KERNEL);
+ if (!button_matrix) {
+ dev_err(dev, "could not allocate memory for button matrix\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ pdata->button_matrix = button_matrix;
+ for (i = 0; i < keymap; i++) {
+ keycode = KEYCODE(ptr[i]);
+ pdata->button_matrix[i] = keycode;
+ }
+ kfree(ptr);
+
+ return pdata;
+}
+
+#else
+static inline struct mt_matrix_keypad_platform_data *
+mt_matrix_keypad_parse_dt(struct device *dev)
+{
+ dev_err(dev, "no platform data defined\n");
+
+ return ERR_PTR(-EINVAL);
+}
+#endif
+
+static int mt_matrix_keypad_probe(struct platform_device *pdev)
+{
+ struct mt_matrix_keypad_platform_data *pdata;
+ struct mt_matrix_keypad *keypad;
+ struct input_dev *input_dev;
+ int err;
+ int row, col, index;
+
+ dev_info(&pdev->dev, "[%s]: Probe\n", MODULE_NAME);
+ pdata = dev_get_platdata(&pdev->dev);
+
+ if (!pdata) {
+ pdata = mt_matrix_keypad_parse_dt(&pdev->dev);
+ if (IS_ERR(pdata)) {
+ dev_err(&pdev->dev, "Mt platform data not defined\n");
+ return PTR_ERR(pdata);
+ }
+ }
+
+ err = pdata->line_gpios[0];
+ if (err < 0)
+ return dev_err_probe(
+ &pdev->dev, err,
+ "Could not register gpio chip for mt matrix keypad\n");
+
+ keypad = kzalloc(sizeof(struct mt_matrix_keypad), GFP_KERNEL);
+ input_dev = input_allocate_device();
+
+ if (!keypad || !input_dev) {
+ dev_err(&pdev->dev, "[%s]: Allocation Failed\n", MODULE_NAME);
+ err = -ENOMEM;
+ goto err_free_mem;
+ }
+
+ init_phase(pdata);
+ keypad->input_dev = input_dev;
+ keypad->pdata = pdata;
+ keypad->stopped = true;
+ INIT_DELAYED_WORK(&keypad->work, mt_matrix_keypad_scan);
+ spin_lock_init(&keypad->lock);
+
+ input_dev->name = pdev->name;
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->dev.parent = &pdev->dev;
+ input_dev->open = mt_matrix_keypad_start;
+ input_dev->close = mt_matrix_keypad_stop;
+
+ if (!pdata->no_autorepeat)
+ __set_bit(EV_REP, input_dev->evbit);
+
+ input_set_capability(input_dev, EV_MSC, MSC_SCAN);
+
+ for (row = 1; row < pdata->num_line_gpios; row++) {
+ for (col = 0; col < row; col++) {
+ index = (row * pdata->num_line_gpios) + col;
+ if (pdata->button_matrix[index] !=
+ pdata->button_matrix[0]) {
+ input_set_capability(
+ input_dev, EV_KEY,
+ pdata->button_matrix[index]);
+ }
+ }
+ }
+
+ input_set_drvdata(input_dev, keypad);
+ err = mt_matrix_keypad_init_gpio(pdev, keypad);
+
+ if (err)
+ goto err_free_mem;
+
+ button_hdl_init(pdata);
+
+ err = input_register_device(keypad->input_dev);
+
+ if (err)
+ goto err_free_gpio;
+
+ device_init_wakeup(&pdev->dev, pdata->wakeup);
+ platform_set_drvdata(pdev, keypad);
+
+ return 0;
+
+err_free_gpio:
+ mt_matrix_keypad_free_gpio(keypad);
+
+err_free_mem:
+ input_free_device(input_dev);
+ kfree(keypad);
+ return err;
+}
+
+static int mt_matrix_keypad_remove(struct platform_device *pdev)
+{
+ struct mt_matrix_keypad *keypad = platform_get_drvdata(pdev);
+
+ device_init_wakeup(&pdev->dev, 0);
+ input_unregister_device(keypad->input_dev);
+ mt_matrix_keypad_free_gpio(keypad);
+ kfree(keypad);
+
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id mt_matrix_keypad_dt_match[] = {
+ { .compatible = "gpio-mt-matrix-keypad" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, mt_matrix_keypad_dt_match);
+#endif
+
+static struct platform_driver mt_matrix_keypad_driver = {
+ .probe = mt_matrix_keypad_probe,
+ .remove = mt_matrix_keypad_remove,
+ .driver = {
+ .name = "mt-matrix-keypad",
+ .pm = &mt_matrix_keypad_pm_ops,
+ .of_match_table = of_match_ptr(mt_matrix_keypad_dt_match),
+ },
+};
+module_platform_driver(mt_matrix_keypad_driver);
+
+MODULE_AUTHOR("vinay");
+MODULE_DESCRIPTION("GPIO Driven Mt Matrix Keypad Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mt-matrix-keypad");
diff --git a/include/linux/input/mt_matrix_keypad.h b/include/linux/input/mt_matrix_keypad.h
new file mode 100644
index 000000000000..8c5fbf109dbc
--- /dev/null
+++ b/include/linux/input/mt_matrix_keypad.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _MT_MATRIX_KEYPAD_H
+#define _MT_MATRIX_KEYPAD_H
+
+#include <linux/types.h>
+#include <linux/input.h>
+#include <linux/of.h>
+
+#define MATRIX_MAX_ROWS 32
+#define KEYCODE(keymap) (keymap & 0xFFFF)
+
+struct button_states {
+ uint8_t boPrevious : 1;
+ uint8_t boCurrent : 1;
+ uint8_t boCurrentStateOfHw : 1;
+ uint8_t boCurrentStateOfSw : 1;
+ uint8_t boEnabled : 1;
+ uint8_t boStateAtInit : 1;
+};
+
+union typeEvent {
+ uint8_t ui8Register;
+ struct {
+ uint8_t boGlobalChanged : 1;
+ uint8_t boPressed : 1;
+ uint8_t boReleased : 1;
+ } status;
+};
+
+struct button {
+ uint8_t key;
+ union typeEvent event;
+ struct button_states state;
+};
+
+struct phase {
+ int phase_prepare;
+ int phase_start;
+ int phase_update_button;
+};
+
+struct mt_matrix_keypad_platform_data {
+ const struct mt_keymap_data *keymap_data;
+ const unsigned int *line_gpios;
+ unsigned int num_line_gpios;
+ unsigned int num_of_button;
+ unsigned int col_scan_delay_us;
+ unsigned int debounce_ms;
+ unsigned int clustered_irq;
+ unsigned int clustered_irq_flags;
+
+ bool active_low;
+ bool wakeup;
+ bool no_autorepeat;
+ bool intialize_buttons;
+
+ int8_t scan_phase;
+ int8_t *button_matrix;
+ struct button *button_array;
+ struct phase phase_state;
+};
+
+#endif /* _MT_MATRIX_KEYPAD_H */
--
2.20.1
Hi Gireesh,
On 22-05-04, [email protected] wrote:
> From: Gireesh Hiremath <[email protected]>
>
> add support for keypad driver running on Bosch Guardian
> Dtect board using TI-am335x cpu. Driver implementation
> is based on matrix_keypad.c
pls can you tell me the main difference between the already existing
matrix_keypad.c driver and your driver. If there are only minor
differences I would rather add those to the existing driver.
Regards,
Marco
From: Gireesh Hiremath <[email protected]>
The existing matric_keypad.c use different gpio line for row and colunm,
where in mt_matrix_kepad.c use same gpio line for row as well as column.
a key can be placed at each intersection of a unique row number
not equal to a unique column and they are diagonally symmetric.
Advantage of this is with existed gpio line we can get more keys
example: in matrix_keypad.c for 5 gpio line possible matrix is 2X3 or 3X2
and maximum possible keys are 6 but
in mt_matrix_kepad.c for same 5 gpio line possible matrix is 5X5 and maximum
possible buttons are 10, below table will discribe that
------------------------------------------------------
|Row\Col |GPIO 0 | GPIO 1 | GPIO 2 | GPIO 3 | GPIO 4 |
------------------------------------------------------
| GPIO 0 | X | KEY_9 | KEY_2 | KEY_3 | KEY_1 |
------------------------------------------------------
| GPIO 1 | KEY_9 | X | KEY_6 | KEY_5 | KEY_0 |
------------------------------------------------------
| GPIO 2 | KEY_2 | KEY_6 | X | KEY_4 | KEY_7 |
------------------------------------------------------
| GPIO 3 | KEY_3 | KEY_5 | KEY_4 | X | KEY_8 |
------------------------------------------------------
| GPIO 4 | KEY_1 | KEY_0 | KEY_7 | KEY_8 | X |
------------------------------------------------------
X - invalid key
KEY_x - preferred key code
both matric_keypad.c and mt_matrix_kepad.c logically operate differently,
my openion is not to merge both.
On 22-05-04, [email protected] wrote:
> From: Gireesh Hiremath <[email protected]>
>
> The existing matric_keypad.c use different gpio line for row and colunm,
> where in mt_matrix_kepad.c use same gpio line for row as well as column.
> a key can be placed at each intersection of a unique row number
> not equal to a unique column and they are diagonally symmetric.
> Advantage of this is with existed gpio line we can get more keys
>
> example: in matrix_keypad.c for 5 gpio line possible matrix is 2X3 or 3X2
> and maximum possible keys are 6 but
> in mt_matrix_kepad.c for same 5 gpio line possible matrix is 5X5 and maximum
> possible buttons are 10, below table will discribe that
Nobody should stop you to increase the amount of max. possible keys, so
this isn't a real block.
> ------------------------------------------------------
> |Row\Col |GPIO 0 | GPIO 1 | GPIO 2 | GPIO 3 | GPIO 4 |
> ------------------------------------------------------
> | GPIO 0 | X | KEY_9 | KEY_2 | KEY_3 | KEY_1 |
> ------------------------------------------------------
> | GPIO 1 | KEY_9 | X | KEY_6 | KEY_5 | KEY_0 |
> ------------------------------------------------------
> | GPIO 2 | KEY_2 | KEY_6 | X | KEY_4 | KEY_7 |
> ------------------------------------------------------
> | GPIO 3 | KEY_3 | KEY_5 | KEY_4 | X | KEY_8 |
> ------------------------------------------------------
> | GPIO 4 | KEY_1 | KEY_0 | KEY_7 | KEY_8 | X |
> ------------------------------------------------------
> X - invalid key
> KEY_x - preferred key code
That should be pointed somewhere very clearly, thanks for the
description. Also what is than the benefit of the original matrix_keypad
driver?
> both matric_keypad.c and mt_matrix_kepad.c logically operate differently,
> my openion is not to merge both.
IMHO from the user/system-integrator pov it is looking the same and so
one driver should be fine. To distinguish between both modes we could
add dt-property or add a new dt-compatible like "gpio-matrix-keypad-v2".
Regards,
Marco
On 04/05/2022 16:14, Marco Felsch wrote:
> On 22-05-04, [email protected] wrote:
>> From: Gireesh Hiremath <[email protected]>
>>
>> The existing matric_keypad.c use different gpio line for row and colunm,
>> where in mt_matrix_kepad.c use same gpio line for row as well as column.
>> a key can be placed at each intersection of a unique row number
>> not equal to a unique column and they are diagonally symmetric.
>> Advantage of this is with existed gpio line we can get more keys
>>
>> example: in matrix_keypad.c for 5 gpio line possible matrix is 2X3 or 3X2
>> and maximum possible keys are 6 but
>> in mt_matrix_kepad.c for same 5 gpio line possible matrix is 5X5 and maximum
>> possible buttons are 10, below table will discribe that
>
> Nobody should stop you to increase the amount of max. possible keys, so
> this isn't a real block.
>
>> ------------------------------------------------------
>> |Row\Col |GPIO 0 | GPIO 1 | GPIO 2 | GPIO 3 | GPIO 4 |
>> ------------------------------------------------------
>> | GPIO 0 | X | KEY_9 | KEY_2 | KEY_3 | KEY_1 |
>> ------------------------------------------------------
>> | GPIO 1 | KEY_9 | X | KEY_6 | KEY_5 | KEY_0 |
>> ------------------------------------------------------
>> | GPIO 2 | KEY_2 | KEY_6 | X | KEY_4 | KEY_7 |
>> ------------------------------------------------------
>> | GPIO 3 | KEY_3 | KEY_5 | KEY_4 | X | KEY_8 |
>> ------------------------------------------------------
>> | GPIO 4 | KEY_1 | KEY_0 | KEY_7 | KEY_8 | X |
>> ------------------------------------------------------
>> X - invalid key
>> KEY_x - preferred key code
>
> That should be pointed somewhere very clearly, thanks for the
> description. Also what is than the benefit of the original matrix_keypad
> driver?
It looks like this driver has smaller number of features than
matrix-keypad, so it should be integrated into the matrix-keypad.
matrix-keypad features are superset to this one.
Best regards,
Krzysztof
Hi,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on tmlind-omap/for-next]
[also build test WARNING on next-20220504]
[cannot apply to dtor-input/next robh/for-next balbi-usb/testing/next v5.18-rc5]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/intel-lab-lkp/linux/commits/Gireesh-Hiremath-in-bosch-com/ARM-dts-am335x-Guardian-switch-to-AM33XX_PADCONF-pinmux-macro/20220504-185623
base: https://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git for-next
config: sh-allmodconfig (https://download.01.org/0day-ci/archive/20220504/[email protected]/config)
compiler: sh4-linux-gcc (GCC) 11.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/8dae1bf10aa8e74feb1bca5eb708e98e9492a587
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Gireesh-Hiremath-in-bosch-com/ARM-dts-am335x-Guardian-switch-to-AM33XX_PADCONF-pinmux-macro/20220504-185623
git checkout 8dae1bf10aa8e74feb1bca5eb708e98e9492a587
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.3.0 make.cross W=1 O=build_dir ARCH=sh SHELL=/bin/bash drivers/input/keyboard/
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>
All warnings (new ones prefixed by >>):
>> drivers/input/keyboard/mt_matrix_keypad.c:51:6: warning: no previous prototype for 'init_phase' [-Wmissing-prototypes]
51 | void init_phase(struct mt_matrix_keypad_platform_data *pdata)
| ^~~~~~~~~~
>> drivers/input/keyboard/mt_matrix_keypad.c:58:6: warning: no previous prototype for 'button_init' [-Wmissing-prototypes]
58 | void button_init(struct button *btn, bool btn_hw_state, int key)
| ^~~~~~~~~~~
>> drivers/input/keyboard/mt_matrix_keypad.c:70:1: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
70 | const struct button_states get_button_state(struct button *btn)
| ^~~~~
>> drivers/input/keyboard/mt_matrix_keypad.c:70:28: warning: no previous prototype for 'get_button_state' [-Wmissing-prototypes]
70 | const struct button_states get_button_state(struct button *btn)
| ^~~~~~~~~~~~~~~~
>> drivers/input/keyboard/mt_matrix_keypad.c:75:17: warning: no previous prototype for 'get_and_clear_events' [-Wmissing-prototypes]
75 | union typeEvent get_and_clear_events(struct button *btn)
| ^~~~~~~~~~~~~~~~~~~~
>> drivers/input/keyboard/mt_matrix_keypad.c:84:9: warning: no previous prototype for 'get_btn_index' [-Wmissing-prototypes]
84 | uint8_t get_btn_index(struct mt_matrix_keypad_platform_data *pdata, int btn_key)
| ^~~~~~~~~~~~~
>> drivers/input/keyboard/mt_matrix_keypad.c:95:6: warning: no previous prototype for 'set_btn_state_by_hw' [-Wmissing-prototypes]
95 | void set_btn_state_by_hw(struct button *btn, bool boButtonState)
| ^~~~~~~~~~~~~~~~~~~
>> drivers/input/keyboard/mt_matrix_keypad.c:100:6: warning: no previous prototype for 'check_button_changes' [-Wmissing-prototypes]
100 | bool check_button_changes(struct button *btn)
| ^~~~~~~~~~~~~~~~~~~~
drivers/input/keyboard/mt_matrix_keypad.c:124:1: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
124 | const struct button_states
| ^~~~~
>> drivers/input/keyboard/mt_matrix_keypad.c:125:1: warning: no previous prototype for 'get_btn_id_state' [-Wmissing-prototypes]
125 | get_btn_id_state(const struct mt_matrix_keypad_platform_data *pdata,
| ^~~~~~~~~~~~~~~~
>> drivers/input/keyboard/mt_matrix_keypad.c:135:1: warning: no previous prototype for 'get_and_clear_btn_events' [-Wmissing-prototypes]
135 | get_and_clear_btn_events(const struct mt_matrix_keypad_platform_data *pdata,
| ^~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/input/keyboard/mt_matrix_keypad.c:144:6: warning: no previous prototype for 'button_hdl_init' [-Wmissing-prototypes]
144 | void button_hdl_init(struct mt_matrix_keypad_platform_data *pdata)
| ^~~~~~~~~~~~~~~
>> drivers/input/keyboard/mt_matrix_keypad.c:171:6: warning: no previous prototype for 'on_button_event' [-Wmissing-prototypes]
171 | bool on_button_event(const struct mt_matrix_keypad_platform_data *pdata,
| ^~~~~~~~~~~~~~~
>> drivers/input/keyboard/mt_matrix_keypad.c:196:6: warning: no previous prototype for 'process_button_events' [-Wmissing-prototypes]
196 | void process_button_events(const struct mt_matrix_keypad_platform_data *pdata,
| ^~~~~~~~~~~~~~~~~~~~~
>> drivers/input/keyboard/mt_matrix_keypad.c:219:6: warning: no previous prototype for 'update_buttons' [-Wmissing-prototypes]
219 | void update_buttons(struct mt_matrix_keypad_platform_data *pdata,
| ^~~~~~~~~~~~~~
vim +/init_phase +51 drivers/input/keyboard/mt_matrix_keypad.c
43
44 static bool
45 get_gpio_line_value(const struct mt_matrix_keypad_platform_data *pdata,
46 int row);
47 static void
48 activate_line_driving(const struct mt_matrix_keypad_platform_data *pdata,
49 int line, bool on);
50
> 51 void init_phase(struct mt_matrix_keypad_platform_data *pdata)
52 {
53 pdata->phase_state.phase_prepare = -1;
54 pdata->phase_state.phase_start = 0;
55 pdata->phase_state.phase_update_button = pdata->num_line_gpios;
56 }
57
> 58 void button_init(struct button *btn, bool btn_hw_state, int key)
59 {
60 btn->state.boPrevious = btn_hw_state;
61 btn->state.boCurrentStateOfHw = btn_hw_state;
62 btn->state.boCurrentStateOfSw = false;
63 btn->state.boCurrent = btn_hw_state;
64 btn->state.boEnabled = true;
65 btn->state.boStateAtInit = btn_hw_state;
66 btn->event.ui8Register = 0;
67 btn->key = key;
68 }
69
> 70 const struct button_states get_button_state(struct button *btn)
71 {
72 return btn->state;
73 }
74
> 75 union typeEvent get_and_clear_events(struct button *btn)
76 {
77 union typeEvent beTemp = btn->event;
78
79 btn->event.ui8Register = 0;
80
81 return beTemp;
82 }
83
> 84 uint8_t get_btn_index(struct mt_matrix_keypad_platform_data *pdata, int btn_key)
85 {
86 uint8_t i;
87
88 for (i = 0; i < pdata->num_of_button; i++) {
89 if (pdata->button_array[i].key == btn_key)
90 break;
91 }
92 return i;
93 }
94
> 95 void set_btn_state_by_hw(struct button *btn, bool boButtonState)
96 {
97 btn->state.boCurrentStateOfHw = boButtonState;
98 }
99
> 100 bool check_button_changes(struct button *btn)
101 {
102 btn->state.boPrevious = btn->state.boCurrent;
103 btn->state.boCurrent =
104 btn->state.boCurrentStateOfHw || btn->state.boCurrentStateOfSw;
105
106 /* Check if Button is pressed */
107 if ((btn->state.boPrevious == false) &&
108 (btn->state.boCurrent == true)) {
109 btn->event.status.boPressed = true;
110 }
111
112 /* Check if Button is released */
113 else if ((btn->state.boPrevious == true) &&
114 (btn->state.boCurrent == false)) {
115 btn->event.status.boReleased = true;
116 }
117
118 if (btn->event.ui8Register != 0)
119 btn->event.status.boGlobalChanged = true;
120
121 return btn->event.status.boGlobalChanged;
122 }
123
> 124 const struct button_states
> 125 get_btn_id_state(const struct mt_matrix_keypad_platform_data *pdata,
126 int btn_index)
127 {
128 if (btn_index < pdata->num_of_button)
129 return get_button_state(&pdata->button_array[btn_index]);
130 else
131 return get_button_state(&pdata->button_array[0]);
132 }
133
134 union typeEvent
> 135 get_and_clear_btn_events(const struct mt_matrix_keypad_platform_data *pdata,
136 int btn_index)
137 {
138 if (btn_index < pdata->num_of_button)
139 return get_and_clear_events(&pdata->button_array[btn_index]);
140 else
141 return get_and_clear_events(&pdata->button_array[0]);
142 }
143
> 144 void button_hdl_init(struct mt_matrix_keypad_platform_data *pdata)
145 {
146 int row, col, index;
147 int i;
148
149 pdata->scan_phase = pdata->phase_state.phase_prepare;
150 pdata->intialize_buttons = true;
151
152 /* Init Button Objects, will be reinited once states are captured */
153 i = 0;
154 for (row = 1; row < pdata->num_line_gpios; row++)
155 for (col = 0; col < row; col++) {
156 index = (row * pdata->num_line_gpios) + col;
157 if (pdata->button_matrix[index] !=
158 pdata->button_matrix[0]) {
159 if (i < pdata->num_of_button) {
160 button_init(
161 &pdata->button_array[i], false,
162 pdata->button_matrix[index]);
163 i++;
164 }
165 }
166 }
167
168 pr_debug("[%s]: %s Done\n", MODULE_NAME, __func__);
169 }
170
> 171 bool on_button_event(const struct mt_matrix_keypad_platform_data *pdata,
172 int btn_index, union typeEvent btn_event,
173 struct input_dev *input_dev)
174 {
175 bool any_btn_served = true;
176 unsigned int key_code = 0;
177 int key_value = 0;
178
179 key_code = pdata->button_array[btn_index].key;
180
181 if (btn_event.status.boPressed) {
182 key_value = 1;
183 pr_debug("[%s]:%d Pressed\n", MODULE_NAME, key_code);
184 }
185
186 if (btn_event.status.boReleased) {
187 key_value = 0;
188 pr_debug("[%s]:%d Released\n", MODULE_NAME, key_code);
189 }
190
191 input_report_key(input_dev, key_code, key_value);
192 input_sync(input_dev);
193 return any_btn_served;
194 }
195
> 196 void process_button_events(const struct mt_matrix_keypad_platform_data *pdata,
197 struct input_dev *input_dev)
198 {
199 int btn_index;
200 bool any_btn_served = false;
201
202 for (btn_index = 0; btn_index < pdata->num_of_button; btn_index++) {
203 const union typeEvent beEvent =
204 get_and_clear_btn_events(pdata, (int)btn_index);
205
206 if (beEvent.status.boGlobalChanged) {
207 const struct button_states bsState =
208 get_btn_id_state(pdata, (int)btn_index);
209
210 if (bsState.boEnabled) {
211 any_btn_served |=
212 on_button_event(pdata, (int)btn_index,
213 beEvent, input_dev);
214 }
215 }
216 }
217 }
218
> 219 void update_buttons(struct mt_matrix_keypad_platform_data *pdata,
220 struct input_dev *input_dev)
221 {
222 if (pdata->scan_phase == pdata->phase_state.phase_prepare) {
223 pdata->scan_phase = pdata->phase_state.phase_start;
224 activate_line_driving(pdata, (int)pdata->scan_phase, true);
225 } else if (pdata->scan_phase ==
226 pdata->phase_state.phase_update_button) {
227 bool btn_changes_occured = false;
228 int btn_index;
229
230 if (pdata->intialize_buttons) {
231 int i;
232
233 pdata->intialize_buttons = false;
234
235 for (i = 0; i < pdata->num_of_button; i++) {
236 const bool btn_curr_hw_state =
237 get_button_state(
238 &pdata->button_array[i])
239 .boCurrentStateOfHw;
240 button_init(&pdata->button_array[i],
241 btn_curr_hw_state,
242 pdata->button_array[i].key);
243 }
244 }
245
246 for (btn_index = 0; btn_index < pdata->num_of_button;
247 btn_index++) {
248 btn_changes_occured |= check_button_changes(
249 &pdata->button_array[btn_index]);
250 }
251
252 if (btn_changes_occured)
253 process_button_events(pdata, input_dev);
254
255 pdata->scan_phase = pdata->phase_state.phase_start;
256 } else {
257 uint8_t *btn_keylines;
258 uint8_t number_of_buttons_pressed = 0;
259 uint8_t btn_index;
260 uint8_t btn_key;
261 uint16_t index;
262 int i;
263
264 btn_keylines = kcalloc(pdata->num_line_gpios, sizeof(uint8_t),
265 GFP_KERNEL);
266 for (i = 0; i < pdata->num_line_gpios; i++) {
267 index = (pdata->scan_phase * pdata->num_line_gpios) + i;
268 btn_key = pdata->button_matrix[index];
269 btn_keylines[i] = false;
270
271 if ((btn_key != pdata->button_matrix[0]) &&
272 (get_gpio_line_value(pdata, (int)i) != false)) {
273 btn_keylines[i] = true;
274 number_of_buttons_pressed++;
275 }
276 }
277 if (number_of_buttons_pressed < 2) {
278 for (i = 0; i < pdata->num_line_gpios; i++) {
279 index = (pdata->scan_phase *
280 pdata->num_line_gpios) +
281 i;
282 btn_key = pdata->button_matrix[index];
283 if (btn_key != pdata->button_matrix[0]) {
284 btn_index =
285 get_btn_index(pdata, btn_key);
286 set_btn_state_by_hw(
287 &pdata->button_array[btn_index],
288 btn_keylines[i]);
289 }
290 }
291 }
292
293 kfree(btn_keylines);
294 activate_line_driving(pdata, (int)pdata->scan_phase, false);
295 pdata->scan_phase++;
296 activate_line_driving(
297 pdata, (int)(pdata->scan_phase % pdata->num_line_gpios),
298 true);
299 }
300 }
301
--
0-DAY CI Kernel Test Service
https://01.org/lkp
Hi,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on tmlind-omap/for-next]
[also build test WARNING on next-20220504]
[cannot apply to dtor-input/next robh/for-next v5.18-rc5]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/intel-lab-lkp/linux/commits/Gireesh-Hiremath-in-bosch-com/ARM-dts-am335x-Guardian-switch-to-AM33XX_PADCONF-pinmux-macro/20220504-185623
base: https://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git for-next
config: x86_64-allmodconfig (https://download.01.org/0day-ci/archive/20220505/[email protected]/config)
compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project 363b3a645a1e30011cc8da624f13dac5fd915628)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/8dae1bf10aa8e74feb1bca5eb708e98e9492a587
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Gireesh-Hiremath-in-bosch-com/ARM-dts-am335x-Guardian-switch-to-AM33XX_PADCONF-pinmux-macro/20220504-185623
git checkout 8dae1bf10aa8e74feb1bca5eb708e98e9492a587
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/input/keyboard/
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>
All warnings (new ones prefixed by >>):
>> drivers/input/keyboard/mt_matrix_keypad.c:51:6: warning: no previous prototype for function 'init_phase' [-Wmissing-prototypes]
void init_phase(struct mt_matrix_keypad_platform_data *pdata)
^
drivers/input/keyboard/mt_matrix_keypad.c:51:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
void init_phase(struct mt_matrix_keypad_platform_data *pdata)
^
static
>> drivers/input/keyboard/mt_matrix_keypad.c:58:6: warning: no previous prototype for function 'button_init' [-Wmissing-prototypes]
void button_init(struct button *btn, bool btn_hw_state, int key)
^
drivers/input/keyboard/mt_matrix_keypad.c:58:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
void button_init(struct button *btn, bool btn_hw_state, int key)
^
static
>> drivers/input/keyboard/mt_matrix_keypad.c:70:1: warning: 'const' type qualifier on return type has no effect [-Wignored-qualifiers]
const struct button_states get_button_state(struct button *btn)
^~~~~~
>> drivers/input/keyboard/mt_matrix_keypad.c:70:28: warning: no previous prototype for function 'get_button_state' [-Wmissing-prototypes]
const struct button_states get_button_state(struct button *btn)
^
drivers/input/keyboard/mt_matrix_keypad.c:70:7: note: declare 'static' if the function is not intended to be used outside of this translation unit
const struct button_states get_button_state(struct button *btn)
^
static
>> drivers/input/keyboard/mt_matrix_keypad.c:75:17: warning: no previous prototype for function 'get_and_clear_events' [-Wmissing-prototypes]
union typeEvent get_and_clear_events(struct button *btn)
^
drivers/input/keyboard/mt_matrix_keypad.c:75:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
union typeEvent get_and_clear_events(struct button *btn)
^
static
>> drivers/input/keyboard/mt_matrix_keypad.c:84:9: warning: no previous prototype for function 'get_btn_index' [-Wmissing-prototypes]
uint8_t get_btn_index(struct mt_matrix_keypad_platform_data *pdata, int btn_key)
^
drivers/input/keyboard/mt_matrix_keypad.c:84:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
uint8_t get_btn_index(struct mt_matrix_keypad_platform_data *pdata, int btn_key)
^
static
>> drivers/input/keyboard/mt_matrix_keypad.c:95:6: warning: no previous prototype for function 'set_btn_state_by_hw' [-Wmissing-prototypes]
void set_btn_state_by_hw(struct button *btn, bool boButtonState)
^
drivers/input/keyboard/mt_matrix_keypad.c:95:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
void set_btn_state_by_hw(struct button *btn, bool boButtonState)
^
static
>> drivers/input/keyboard/mt_matrix_keypad.c:100:6: warning: no previous prototype for function 'check_button_changes' [-Wmissing-prototypes]
bool check_button_changes(struct button *btn)
^
drivers/input/keyboard/mt_matrix_keypad.c:100:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
bool check_button_changes(struct button *btn)
^
static
drivers/input/keyboard/mt_matrix_keypad.c:124:1: warning: 'const' type qualifier on return type has no effect [-Wignored-qualifiers]
const struct button_states
^~~~~~
>> drivers/input/keyboard/mt_matrix_keypad.c:125:1: warning: no previous prototype for function 'get_btn_id_state' [-Wmissing-prototypes]
get_btn_id_state(const struct mt_matrix_keypad_platform_data *pdata,
^
drivers/input/keyboard/mt_matrix_keypad.c:124:7: note: declare 'static' if the function is not intended to be used outside of this translation unit
const struct button_states
^
static
>> drivers/input/keyboard/mt_matrix_keypad.c:135:1: warning: no previous prototype for function 'get_and_clear_btn_events' [-Wmissing-prototypes]
get_and_clear_btn_events(const struct mt_matrix_keypad_platform_data *pdata,
^
drivers/input/keyboard/mt_matrix_keypad.c:134:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
union typeEvent
^
static
>> drivers/input/keyboard/mt_matrix_keypad.c:144:6: warning: no previous prototype for function 'button_hdl_init' [-Wmissing-prototypes]
void button_hdl_init(struct mt_matrix_keypad_platform_data *pdata)
^
drivers/input/keyboard/mt_matrix_keypad.c:144:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
void button_hdl_init(struct mt_matrix_keypad_platform_data *pdata)
^
static
>> drivers/input/keyboard/mt_matrix_keypad.c:171:6: warning: no previous prototype for function 'on_button_event' [-Wmissing-prototypes]
bool on_button_event(const struct mt_matrix_keypad_platform_data *pdata,
^
drivers/input/keyboard/mt_matrix_keypad.c:171:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
bool on_button_event(const struct mt_matrix_keypad_platform_data *pdata,
^
static
>> drivers/input/keyboard/mt_matrix_keypad.c:200:7: warning: variable 'any_btn_served' set but not used [-Wunused-but-set-variable]
bool any_btn_served = false;
^
>> drivers/input/keyboard/mt_matrix_keypad.c:196:6: warning: no previous prototype for function 'process_button_events' [-Wmissing-prototypes]
void process_button_events(const struct mt_matrix_keypad_platform_data *pdata,
^
drivers/input/keyboard/mt_matrix_keypad.c:196:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
void process_button_events(const struct mt_matrix_keypad_platform_data *pdata,
^
static
>> drivers/input/keyboard/mt_matrix_keypad.c:219:6: warning: no previous prototype for function 'update_buttons' [-Wmissing-prototypes]
void update_buttons(struct mt_matrix_keypad_platform_data *pdata,
^
drivers/input/keyboard/mt_matrix_keypad.c:219:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
void update_buttons(struct mt_matrix_keypad_platform_data *pdata,
^
static
16 warnings generated.
vim +/init_phase +51 drivers/input/keyboard/mt_matrix_keypad.c
43
44 static bool
45 get_gpio_line_value(const struct mt_matrix_keypad_platform_data *pdata,
46 int row);
47 static void
48 activate_line_driving(const struct mt_matrix_keypad_platform_data *pdata,
49 int line, bool on);
50
> 51 void init_phase(struct mt_matrix_keypad_platform_data *pdata)
52 {
53 pdata->phase_state.phase_prepare = -1;
54 pdata->phase_state.phase_start = 0;
55 pdata->phase_state.phase_update_button = pdata->num_line_gpios;
56 }
57
> 58 void button_init(struct button *btn, bool btn_hw_state, int key)
59 {
60 btn->state.boPrevious = btn_hw_state;
61 btn->state.boCurrentStateOfHw = btn_hw_state;
62 btn->state.boCurrentStateOfSw = false;
63 btn->state.boCurrent = btn_hw_state;
64 btn->state.boEnabled = true;
65 btn->state.boStateAtInit = btn_hw_state;
66 btn->event.ui8Register = 0;
67 btn->key = key;
68 }
69
> 70 const struct button_states get_button_state(struct button *btn)
71 {
72 return btn->state;
73 }
74
> 75 union typeEvent get_and_clear_events(struct button *btn)
76 {
77 union typeEvent beTemp = btn->event;
78
79 btn->event.ui8Register = 0;
80
81 return beTemp;
82 }
83
> 84 uint8_t get_btn_index(struct mt_matrix_keypad_platform_data *pdata, int btn_key)
85 {
86 uint8_t i;
87
88 for (i = 0; i < pdata->num_of_button; i++) {
89 if (pdata->button_array[i].key == btn_key)
90 break;
91 }
92 return i;
93 }
94
> 95 void set_btn_state_by_hw(struct button *btn, bool boButtonState)
96 {
97 btn->state.boCurrentStateOfHw = boButtonState;
98 }
99
> 100 bool check_button_changes(struct button *btn)
101 {
102 btn->state.boPrevious = btn->state.boCurrent;
103 btn->state.boCurrent =
104 btn->state.boCurrentStateOfHw || btn->state.boCurrentStateOfSw;
105
106 /* Check if Button is pressed */
107 if ((btn->state.boPrevious == false) &&
108 (btn->state.boCurrent == true)) {
109 btn->event.status.boPressed = true;
110 }
111
112 /* Check if Button is released */
113 else if ((btn->state.boPrevious == true) &&
114 (btn->state.boCurrent == false)) {
115 btn->event.status.boReleased = true;
116 }
117
118 if (btn->event.ui8Register != 0)
119 btn->event.status.boGlobalChanged = true;
120
121 return btn->event.status.boGlobalChanged;
122 }
123
124 const struct button_states
> 125 get_btn_id_state(const struct mt_matrix_keypad_platform_data *pdata,
126 int btn_index)
127 {
128 if (btn_index < pdata->num_of_button)
129 return get_button_state(&pdata->button_array[btn_index]);
130 else
131 return get_button_state(&pdata->button_array[0]);
132 }
133
134 union typeEvent
> 135 get_and_clear_btn_events(const struct mt_matrix_keypad_platform_data *pdata,
136 int btn_index)
137 {
138 if (btn_index < pdata->num_of_button)
139 return get_and_clear_events(&pdata->button_array[btn_index]);
140 else
141 return get_and_clear_events(&pdata->button_array[0]);
142 }
143
> 144 void button_hdl_init(struct mt_matrix_keypad_platform_data *pdata)
145 {
146 int row, col, index;
147 int i;
148
149 pdata->scan_phase = pdata->phase_state.phase_prepare;
150 pdata->intialize_buttons = true;
151
152 /* Init Button Objects, will be reinited once states are captured */
153 i = 0;
154 for (row = 1; row < pdata->num_line_gpios; row++)
155 for (col = 0; col < row; col++) {
156 index = (row * pdata->num_line_gpios) + col;
157 if (pdata->button_matrix[index] !=
158 pdata->button_matrix[0]) {
159 if (i < pdata->num_of_button) {
160 button_init(
161 &pdata->button_array[i], false,
162 pdata->button_matrix[index]);
163 i++;
164 }
165 }
166 }
167
168 pr_debug("[%s]: %s Done\n", MODULE_NAME, __func__);
169 }
170
> 171 bool on_button_event(const struct mt_matrix_keypad_platform_data *pdata,
172 int btn_index, union typeEvent btn_event,
173 struct input_dev *input_dev)
174 {
175 bool any_btn_served = true;
176 unsigned int key_code = 0;
177 int key_value = 0;
178
179 key_code = pdata->button_array[btn_index].key;
180
181 if (btn_event.status.boPressed) {
182 key_value = 1;
183 pr_debug("[%s]:%d Pressed\n", MODULE_NAME, key_code);
184 }
185
186 if (btn_event.status.boReleased) {
187 key_value = 0;
188 pr_debug("[%s]:%d Released\n", MODULE_NAME, key_code);
189 }
190
191 input_report_key(input_dev, key_code, key_value);
192 input_sync(input_dev);
193 return any_btn_served;
194 }
195
> 196 void process_button_events(const struct mt_matrix_keypad_platform_data *pdata,
197 struct input_dev *input_dev)
198 {
199 int btn_index;
> 200 bool any_btn_served = false;
201
202 for (btn_index = 0; btn_index < pdata->num_of_button; btn_index++) {
203 const union typeEvent beEvent =
204 get_and_clear_btn_events(pdata, (int)btn_index);
205
206 if (beEvent.status.boGlobalChanged) {
207 const struct button_states bsState =
208 get_btn_id_state(pdata, (int)btn_index);
209
210 if (bsState.boEnabled) {
211 any_btn_served |=
212 on_button_event(pdata, (int)btn_index,
213 beEvent, input_dev);
214 }
215 }
216 }
217 }
218
> 219 void update_buttons(struct mt_matrix_keypad_platform_data *pdata,
220 struct input_dev *input_dev)
221 {
222 if (pdata->scan_phase == pdata->phase_state.phase_prepare) {
223 pdata->scan_phase = pdata->phase_state.phase_start;
224 activate_line_driving(pdata, (int)pdata->scan_phase, true);
225 } else if (pdata->scan_phase ==
226 pdata->phase_state.phase_update_button) {
227 bool btn_changes_occured = false;
228 int btn_index;
229
230 if (pdata->intialize_buttons) {
231 int i;
232
233 pdata->intialize_buttons = false;
234
235 for (i = 0; i < pdata->num_of_button; i++) {
236 const bool btn_curr_hw_state =
237 get_button_state(
238 &pdata->button_array[i])
239 .boCurrentStateOfHw;
240 button_init(&pdata->button_array[i],
241 btn_curr_hw_state,
242 pdata->button_array[i].key);
243 }
244 }
245
246 for (btn_index = 0; btn_index < pdata->num_of_button;
247 btn_index++) {
248 btn_changes_occured |= check_button_changes(
249 &pdata->button_array[btn_index]);
250 }
251
252 if (btn_changes_occured)
253 process_button_events(pdata, input_dev);
254
255 pdata->scan_phase = pdata->phase_state.phase_start;
256 } else {
257 uint8_t *btn_keylines;
258 uint8_t number_of_buttons_pressed = 0;
259 uint8_t btn_index;
260 uint8_t btn_key;
261 uint16_t index;
262 int i;
263
264 btn_keylines = kcalloc(pdata->num_line_gpios, sizeof(uint8_t),
265 GFP_KERNEL);
266 for (i = 0; i < pdata->num_line_gpios; i++) {
267 index = (pdata->scan_phase * pdata->num_line_gpios) + i;
268 btn_key = pdata->button_matrix[index];
269 btn_keylines[i] = false;
270
271 if ((btn_key != pdata->button_matrix[0]) &&
272 (get_gpio_line_value(pdata, (int)i) != false)) {
273 btn_keylines[i] = true;
274 number_of_buttons_pressed++;
275 }
276 }
277 if (number_of_buttons_pressed < 2) {
278 for (i = 0; i < pdata->num_line_gpios; i++) {
279 index = (pdata->scan_phase *
280 pdata->num_line_gpios) +
281 i;
282 btn_key = pdata->button_matrix[index];
283 if (btn_key != pdata->button_matrix[0]) {
284 btn_index =
285 get_btn_index(pdata, btn_key);
286 set_btn_state_by_hw(
287 &pdata->button_array[btn_index],
288 btn_keylines[i]);
289 }
290 }
291 }
292
293 kfree(btn_keylines);
294 activate_line_driving(pdata, (int)pdata->scan_phase, false);
295 pdata->scan_phase++;
296 activate_line_driving(
297 pdata, (int)(pdata->scan_phase % pdata->num_line_gpios),
298 true);
299 }
300 }
301
--
0-DAY CI Kernel Test Service
https://01.org/lkp