Lines Matching +full:gpio +full:- +full:matrix +full:- +full:keypad
1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Description: keypad driver for ADP5588 and ADP5587
5 * I2C QWERTY Keypad and IO Expander
8 * Copyright (C) 2008-2010 Analog Devices Inc.
14 #include <linux/gpio/consumer.h>
15 #include <linux/gpio/driver.h>
24 #include <linux/pinctrl/pinconf-generic.h>
45 #define KP_LCK_TMR 0x0E /* Keypad Lock1 to Lock2 Timer */
48 #define GPIO_INT_STAT1 0x11 /* GPIO Interrupt Status */
49 #define GPIO_INT_STAT2 0x12 /* GPIO Interrupt Status */
50 #define GPIO_INT_STAT3 0x13 /* GPIO Interrupt Status */
51 #define GPIO_DAT_STAT1 0x14 /* GPIO Data Status, Read twice to clear */
52 #define GPIO_DAT_STAT2 0x15 /* GPIO Data Status, Read twice to clear */
53 #define GPIO_DAT_STAT3 0x16 /* GPIO Data Status, Read twice to clear */
54 #define GPIO_DAT_OUT1 0x17 /* GPIO DATA OUT */
55 #define GPIO_DAT_OUT2 0x18 /* GPIO DATA OUT */
56 #define GPIO_DAT_OUT3 0x19 /* GPIO DATA OUT */
57 #define GPIO_INT_EN1 0x1A /* GPIO Interrupt Enable */
58 #define GPIO_INT_EN2 0x1B /* GPIO Interrupt Enable */
59 #define GPIO_INT_EN3 0x1C /* GPIO Interrupt Enable */
60 #define KP_GPIO1 0x1D /* Keypad or GPIO Selection */
61 #define KP_GPIO2 0x1E /* Keypad or GPIO Selection */
62 #define KP_GPIO3 0x1F /* Keypad or GPIO Selection */
66 #define GPIO_DIR1 0x23 /* GPIO Data Direction */
67 #define GPIO_DIR2 0x24 /* GPIO Data Direction */
68 #define GPIO_DIR3 0x25 /* GPIO Data Direction */
69 #define GPIO_INT_LVL1 0x26 /* GPIO Edge/Level Detect */
70 #define GPIO_INT_LVL2 0x27 /* GPIO Edge/Level Detect */
71 #define GPIO_INT_LVL3 0x28 /* GPIO Edge/Level Detect */
75 #define GPIO_PULL1 0x2C /* GPIO Pull Disable */
76 #define GPIO_PULL2 0x2D /* GPIO Pull Disable */
77 #define GPIO_PULL3 0x2E /* GPIO Pull Disable */
126 * 128 so it fits matrix-keymap maximum number of keys when the full
158 #define ADP5588_ROWS_MAX (GPI_PIN_ROW7 - GPI_PIN_ROW0 + 1)
159 #define ADP5588_COLS_MAX (GPI_PIN_COL9 - GPI_PIN_COL0 + 1)
161 #define ADP5588_GPIMAPSIZE_MAX (GPI_PIN_END - GPI_PIN_BASE + 1)
167 #define KP_SEL(x) (BIT(x) - 1) /* 2^x-1 */
208 dev_err(&client->dev, "Read Error\n"); in adp5588_read()
221 unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]); in adp5588_gpio_get_value()
222 unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]); in adp5588_gpio_get_value()
225 guard(mutex)(&kpad->gpio_lock); in adp5588_gpio_get_value()
227 if (kpad->dir[bank] & bit) in adp5588_gpio_get_value()
228 val = kpad->dat_out[bank]; in adp5588_gpio_get_value()
230 val = adp5588_read(kpad->client, GPIO_DAT_STAT1 + bank); in adp5588_gpio_get_value()
239 unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]); in adp5588_gpio_set_value()
240 unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]); in adp5588_gpio_set_value()
242 guard(mutex)(&kpad->gpio_lock); in adp5588_gpio_set_value()
245 kpad->dat_out[bank] |= bit; in adp5588_gpio_set_value()
247 kpad->dat_out[bank] &= ~bit; in adp5588_gpio_set_value()
249 return adp5588_write(kpad->client, GPIO_DAT_OUT1 + bank, in adp5588_gpio_set_value()
250 kpad->dat_out[bank]); in adp5588_gpio_set_value()
257 unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]); in adp5588_gpio_set_config()
258 unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]); in adp5588_gpio_set_config()
269 return -ENOTSUPP; in adp5588_gpio_set_config()
272 guard(mutex)(&kpad->gpio_lock); in adp5588_gpio_set_config()
275 kpad->pull_dis[bank] |= bit; in adp5588_gpio_set_config()
277 kpad->pull_dis[bank] &= bit; in adp5588_gpio_set_config()
279 return adp5588_write(kpad->client, GPIO_PULL1 + bank, in adp5588_gpio_set_config()
280 kpad->pull_dis[bank]); in adp5588_gpio_set_config()
286 unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]); in adp5588_gpio_direction_input()
287 unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]); in adp5588_gpio_direction_input()
289 guard(mutex)(&kpad->gpio_lock); in adp5588_gpio_direction_input()
291 kpad->dir[bank] &= ~bit; in adp5588_gpio_direction_input()
292 return adp5588_write(kpad->client, GPIO_DIR1 + bank, kpad->dir[bank]); in adp5588_gpio_direction_input()
299 unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]); in adp5588_gpio_direction_output()
300 unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]); in adp5588_gpio_direction_output()
303 guard(mutex)(&kpad->gpio_lock); in adp5588_gpio_direction_output()
305 kpad->dir[bank] |= bit; in adp5588_gpio_direction_output()
308 kpad->dat_out[bank] |= bit; in adp5588_gpio_direction_output()
310 kpad->dat_out[bank] &= ~bit; in adp5588_gpio_direction_output()
312 error = adp5588_write(kpad->client, GPIO_DAT_OUT1 + bank, in adp5588_gpio_direction_output()
313 kpad->dat_out[bank]); in adp5588_gpio_direction_output()
317 error = adp5588_write(kpad->client, GPIO_DIR1 + bank, kpad->dir[bank]); in adp5588_gpio_direction_output()
332 for (i = 0; i < kpad->rows; i++) in adp5588_build_gpiomap()
335 for (i = 0; i < kpad->cols; i++) in adp5588_build_gpiomap()
336 pin_used[i + GPI_PIN_COL_BASE - GPI_PIN_BASE] = true; in adp5588_build_gpiomap()
340 kpad->gpiomap[n_unused++] = i; in adp5588_build_gpiomap()
350 mutex_lock(&kpad->gpio_lock); in adp5588_irq_bus_lock()
360 if (kpad->int_en[i] ^ kpad->irq_mask[i]) { in adp5588_irq_bus_sync_unlock()
361 kpad->int_en[i] = kpad->irq_mask[i]; in adp5588_irq_bus_sync_unlock()
362 adp5588_write(kpad->client, GPI_EM1 + i, kpad->int_en[i]); in adp5588_irq_bus_sync_unlock()
366 mutex_unlock(&kpad->gpio_lock); in adp5588_irq_bus_sync_unlock()
374 unsigned long real_irq = kpad->gpiomap[hwirq]; in adp5588_irq_mask()
376 kpad->irq_mask[ADP5588_BANK(real_irq)] &= ~ADP5588_BIT(real_irq); in adp5588_irq_mask()
385 unsigned long real_irq = kpad->gpiomap[hwirq]; in adp5588_irq_unmask()
388 kpad->irq_mask[ADP5588_BANK(real_irq)] |= ADP5588_BIT(real_irq); in adp5588_irq_unmask()
394 return -EINVAL; in adp5588_irq_set_type()
414 struct device *dev = &kpad->client->dev; in adp5588_gpio_add()
418 kpad->gc.ngpio = adp5588_build_gpiomap(kpad); in adp5588_gpio_add()
419 if (kpad->gc.ngpio == 0) { in adp5588_gpio_add()
424 kpad->gc.parent = &kpad->client->dev; in adp5588_gpio_add()
425 kpad->gc.direction_input = adp5588_gpio_direction_input; in adp5588_gpio_add()
426 kpad->gc.direction_output = adp5588_gpio_direction_output; in adp5588_gpio_add()
427 kpad->gc.get = adp5588_gpio_get_value; in adp5588_gpio_add()
428 kpad->gc.set = adp5588_gpio_set_value; in adp5588_gpio_add()
429 kpad->gc.set_config = adp5588_gpio_set_config; in adp5588_gpio_add()
430 kpad->gc.can_sleep = 1; in adp5588_gpio_add()
432 kpad->gc.base = -1; in adp5588_gpio_add()
433 kpad->gc.label = kpad->client->name; in adp5588_gpio_add()
434 kpad->gc.owner = THIS_MODULE; in adp5588_gpio_add()
436 if (device_property_present(dev, "interrupt-controller")) { in adp5588_gpio_add()
437 if (!kpad->client->irq) { in adp5588_gpio_add()
439 return -EINVAL; in adp5588_gpio_add()
442 girq = &kpad->gc.irq; in adp5588_gpio_add()
444 girq->handler = handle_bad_irq; in adp5588_gpio_add()
445 girq->threaded = true; in adp5588_gpio_add()
448 mutex_init(&kpad->gpio_lock); in adp5588_gpio_add()
450 error = devm_gpiochip_add_data(dev, &kpad->gc, kpad); in adp5588_gpio_add()
457 kpad->dat_out[i] = adp5588_read(kpad->client, in adp5588_gpio_add()
459 kpad->dir[i] = adp5588_read(kpad->client, GPIO_DIR1 + i); in adp5588_gpio_add()
460 kpad->pull_dis[i] = adp5588_read(kpad->client, GPIO_PULL1 + i); in adp5588_gpio_add()
467 const u8 *map, unsigned int gpio, in adp5588_gpiomap_get_hwirq() argument
473 if (map[hwirq] == gpio) in adp5588_gpiomap_get_hwirq()
477 dev_warn_ratelimited(dev, "could not find the hwirq for gpio(%u)\n", gpio); in adp5588_gpiomap_get_hwirq()
485 unsigned int irq, gpio = key_val - GPI_PIN_BASE, irq_type; in adp5588_gpio_irq_handle() local
486 struct i2c_client *client = kpad->client; in adp5588_gpio_irq_handle()
490 hwirq = adp5588_gpiomap_get_hwirq(&client->dev, kpad->gpiomap, in adp5588_gpio_irq_handle()
491 gpio, kpad->gc.ngpio); in adp5588_gpio_irq_handle()
493 dev_err(&client->dev, "Could not get hwirq for key(%u)\n", key_val); in adp5588_gpio_irq_handle()
497 irq = irq_find_mapping(kpad->gc.irq.domain, hwirq); in adp5588_gpio_irq_handle()
503 dev_err(&client->dev, "Could not get irq(%u) data\n", irq); in adp5588_gpio_irq_handle()
523 int key = adp5588_read(kpad->client, KEY_EVENTA + i); in adp5588_report_events()
528 /* gpio line used as IRQ source */ in adp5588_report_events()
531 int row = (key_val - 1) / ADP5588_COLS_MAX; in adp5588_report_events()
532 int col = (key_val - 1) % ADP5588_COLS_MAX; in adp5588_report_events()
533 int code = MATRIX_SCAN_CODE(row, col, kpad->row_shift); in adp5588_report_events()
535 dev_dbg_ratelimited(&kpad->client->dev, in adp5588_report_events()
537 key_val, row, col, kpad->keycode[code]); in adp5588_report_events()
539 input_report_key(kpad->input, in adp5588_report_events()
540 kpad->keycode[code], key_press); in adp5588_report_events()
549 kpad->irq_time = ktime_get(); in adp5588_hard_irq()
557 struct i2c_client *client = kpad->client; in adp5588_thread_irq()
566 if (kpad->delay) { in adp5588_thread_irq()
567 target_time = ktime_add_ms(kpad->irq_time, kpad->delay); in adp5588_thread_irq()
578 dev_err(&client->dev, "Event Overflow Error\n"); in adp5588_thread_irq()
584 input_sync(kpad->input); in adp5588_thread_irq()
595 struct i2c_client *client = kpad->client; in adp5588_setup()
598 ret = adp5588_write(client, KP_GPIO1, KP_SEL(kpad->rows)); in adp5588_setup()
602 ret = adp5588_write(client, KP_GPIO2, KP_SEL(kpad->cols) & 0xFF); in adp5588_setup()
606 ret = adp5588_write(client, KP_GPIO3, KP_SEL(kpad->cols) >> 8); in adp5588_setup()
610 for (i = 0; i < kpad->nkeys_unlock; i++) { in adp5588_setup()
611 ret = adp5588_write(client, UNLOCK1 + i, kpad->unlock_keys[i]); in adp5588_setup()
616 if (kpad->nkeys_unlock) { in adp5588_setup()
641 struct i2c_client *client = kpad->client; in adp5588_fw_parse()
645 * Check if the device is to be operated purely in GPIO mode. To do in adp5588_fw_parse()
646 * so, check that no keypad rows or columns have been specified, in adp5588_fw_parse()
647 * since all GPINS should be configured as GPIO. in adp5588_fw_parse()
649 if (!device_property_present(&client->dev, "keypad,num-rows") && in adp5588_fw_parse()
650 !device_property_present(&client->dev, "keypad,num-columns")) { in adp5588_fw_parse()
651 /* If purely GPIO, skip keypad setup */ in adp5588_fw_parse()
652 kpad->gpio_only = true; in adp5588_fw_parse()
656 ret = matrix_keypad_parse_properties(&client->dev, &kpad->rows, in adp5588_fw_parse()
657 &kpad->cols); in adp5588_fw_parse()
661 if (kpad->rows > ADP5588_ROWS_MAX || kpad->cols > ADP5588_COLS_MAX) { in adp5588_fw_parse()
662 dev_err(&client->dev, "Invalid nr of rows(%u) or cols(%u)\n", in adp5588_fw_parse()
663 kpad->rows, kpad->cols); in adp5588_fw_parse()
664 return -EINVAL; in adp5588_fw_parse()
667 ret = matrix_keypad_build_keymap(NULL, NULL, kpad->rows, kpad->cols, in adp5588_fw_parse()
668 kpad->keycode, kpad->input); in adp5588_fw_parse()
672 kpad->row_shift = get_count_order(kpad->cols); in adp5588_fw_parse()
674 if (device_property_read_bool(&client->dev, "autorepeat")) in adp5588_fw_parse()
675 __set_bit(EV_REP, kpad->input->evbit); in adp5588_fw_parse()
677 kpad->nkeys_unlock = device_property_count_u32(&client->dev, in adp5588_fw_parse()
678 "adi,unlock-keys"); in adp5588_fw_parse()
679 if (kpad->nkeys_unlock <= 0) { in adp5588_fw_parse()
681 kpad->nkeys_unlock = 0; in adp5588_fw_parse()
685 if (kpad->nkeys_unlock > ARRAY_SIZE(kpad->unlock_keys)) { in adp5588_fw_parse()
686 dev_err(&client->dev, "number of unlock keys(%d) > (%zu)\n", in adp5588_fw_parse()
687 kpad->nkeys_unlock, ARRAY_SIZE(kpad->unlock_keys)); in adp5588_fw_parse()
688 return -EINVAL; in adp5588_fw_parse()
691 ret = device_property_read_u32_array(&client->dev, "adi,unlock-keys", in adp5588_fw_parse()
692 kpad->unlock_keys, in adp5588_fw_parse()
693 kpad->nkeys_unlock); in adp5588_fw_parse()
697 for (i = 0; i < kpad->nkeys_unlock; i++) { in adp5588_fw_parse()
703 * part of keypad matrix to be used and if a reliable way of in adp5588_fw_parse()
706 if (kpad->unlock_keys[i] >= kpad->cols * kpad->rows) { in adp5588_fw_parse()
707 dev_err(&client->dev, "Invalid unlock key(%d)\n", in adp5588_fw_parse()
708 kpad->unlock_keys[i]); in adp5588_fw_parse()
709 return -EINVAL; in adp5588_fw_parse()
716 kpad->unlock_keys[i] += 1; in adp5588_fw_parse()
726 struct gpio_desc *gpio; in adp5588_probe() local
731 if (!i2c_check_functionality(client->adapter, in adp5588_probe()
733 dev_err(&client->dev, "SMBUS Byte Data not Supported\n"); in adp5588_probe()
734 return -EIO; in adp5588_probe()
737 kpad = devm_kzalloc(&client->dev, sizeof(*kpad), GFP_KERNEL); in adp5588_probe()
739 return -ENOMEM; in adp5588_probe()
741 input = devm_input_allocate_device(&client->dev); in adp5588_probe()
743 return -ENOMEM; in adp5588_probe()
745 kpad->client = client; in adp5588_probe()
746 kpad->input = input; in adp5588_probe()
752 error = devm_regulator_get_enable(&client->dev, "vcc"); in adp5588_probe()
756 gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH); in adp5588_probe()
757 if (IS_ERR(gpio)) in adp5588_probe()
758 return PTR_ERR(gpio); in adp5588_probe()
760 if (gpio) { in adp5588_probe()
762 gpiod_set_value_cansleep(gpio, 0); in adp5588_probe()
772 kpad->delay = msecs_to_jiffies(WA_DELAYED_READOUT_TIME); in adp5588_probe()
774 input->name = client->name; in adp5588_probe()
775 input->phys = "adp5588-keys/input0"; in adp5588_probe()
779 input->id.bustype = BUS_I2C; in adp5588_probe()
780 input->id.vendor = 0x0001; in adp5588_probe()
781 input->id.product = 0x0001; in adp5588_probe()
782 input->id.version = revid; in adp5588_probe()
786 dev_err(&client->dev, "unable to register input device: %d\n", in adp5588_probe()
799 if (client->irq) { in adp5588_probe()
800 error = devm_request_threaded_irq(&client->dev, client->irq, in adp5588_probe()
803 client->dev.driver->name, kpad); in adp5588_probe()
805 dev_err(&client->dev, "failed to request irq %d: %d\n", in adp5588_probe()
806 client->irq, error); in adp5588_probe()
811 dev_info(&client->dev, "Rev.%d controller\n", revid); in adp5588_probe()
826 if (client->irq) in adp5588_suspend()
827 disable_irq(client->irq); in adp5588_suspend()
836 if (client->irq) in adp5588_resume()
837 enable_irq(client->irq); in adp5588_resume()
845 { "adp5588-keys" },
846 { "adp5587-keys" },
873 MODULE_DESCRIPTION("ADP5588/87 Keypad driver");