Lines Matching +full:i2c +full:- +full:int +full:- +full:rising

1 // SPDX-License-Identifier: GPL-2.0
14 #include <linux/devm-helpers.h>
17 #include <linux/i2c.h>
25 #include <linux/turris-omnia-mcu-interface.h>
26 #include "turris-omnia-mcu.h"
32 /* GPIOs with value read from the 16-bit wide status */
35 [6] = "Front USB3 port over-current",
36 [7] = "Rear USB3 port over-current",
41 /* GPIOs with value read from the 32-bit wide extended status */
64 /* GPIOs with value read from the 16-bit wide extended control status */
106 -1, 0, 0)
131 __bf_shf(OMNIA_EXT_CTL_ ## _name), -1, \
140 return gpio->int_bit != OMNIA_GPIO_INVALID_INT_BIT; in is_int_bit_valid()
144 /* GPIOs with value read from the 16-bit wide status */
163 /* GPIOs with value read from the 32-bit wide extended status */
186 /* GPIOs with value read from the 16-bit wide extended control status */
233 static int omnia_ctl_cmd_locked(struct omnia_mcu *mcu, u8 cmd, u16 val, u16 mask) in omnia_ctl_cmd_locked()
235 unsigned int len; in omnia_ctl_cmd_locked()
257 return omnia_cmd_write(mcu->client, buf, len); in omnia_ctl_cmd_locked()
260 static int omnia_ctl_cmd(struct omnia_mcu *mcu, u8 cmd, u16 val, u16 mask) in omnia_ctl_cmd()
262 guard(mutex)(&mcu->lock); in omnia_ctl_cmd()
267 static int omnia_gpio_request(struct gpio_chip *gc, unsigned int offset) in omnia_gpio_request()
270 return -EINVAL; in omnia_gpio_request()
275 static int omnia_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) in omnia_gpio_get_direction()
280 int val; in omnia_gpio_get_direction()
282 scoped_guard(mutex, &mcu->lock) { in omnia_gpio_get_direction()
283 val = omnia_cmd_read_bit(mcu->client, in omnia_gpio_get_direction()
302 static int omnia_gpio_direction_input(struct gpio_chip *gc, unsigned int offset) in omnia_gpio_direction_input()
312 if (gpio->ctl_cmd) in omnia_gpio_direction_input()
313 return -ENOTSUPP; in omnia_gpio_direction_input()
318 static int omnia_gpio_direction_output(struct gpio_chip *gc, in omnia_gpio_direction_output()
319 unsigned int offset, int value) in omnia_gpio_direction_output()
325 if (!gpio->ctl_cmd) in omnia_gpio_direction_output()
326 return -ENOTSUPP; in omnia_gpio_direction_output()
328 mask = BIT(gpio->ctl_bit); in omnia_gpio_direction_output()
334 return omnia_ctl_cmd(mcu, gpio->ctl_cmd, val, mask); in omnia_gpio_direction_output()
337 static int omnia_gpio_get(struct gpio_chip *gc, unsigned int offset) in omnia_gpio_get()
348 if (gpio->cmd == OMNIA_CMD_GET_STATUS_WORD && in omnia_gpio_get()
349 !(mcu->features & OMNIA_FEAT_NEW_INT_API)) in omnia_gpio_get()
350 return test_bit(gpio->bit, &mcu->last_status); in omnia_gpio_get()
352 guard(mutex)(&mcu->lock); in omnia_gpio_get()
359 if (is_int_bit_valid(gpio) && test_bit(gpio->int_bit, &mcu->is_cached)) in omnia_gpio_get()
360 return test_bit(gpio->int_bit, &mcu->cached); in omnia_gpio_get()
362 return omnia_cmd_read_bit(mcu->client, gpio->cmd, BIT(gpio->bit)); in omnia_gpio_get()
381 static int omnia_gpio_get_multiple(struct gpio_chip *gc, unsigned long *mask, in omnia_gpio_get_multiple()
386 struct i2c_client *client = mcu->client; in omnia_gpio_get_multiple()
387 unsigned int i; in omnia_gpio_get_multiple()
388 int err; in omnia_gpio_get_multiple()
400 guard(mutex)(&mcu->lock); in omnia_gpio_get_multiple()
402 if (mcu->features & OMNIA_FEAT_NEW_INT_API) { in omnia_gpio_get_multiple()
413 sts = mcu->last_status; in omnia_gpio_get_multiple()
441 static void omnia_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) in omnia_gpio_set()
447 if (!gpio->ctl_cmd) in omnia_gpio_set()
450 mask = BIT(gpio->ctl_bit); in omnia_gpio_set()
453 omnia_ctl_cmd(mcu, gpio->ctl_cmd, val, mask); in omnia_gpio_set()
461 unsigned int i; in omnia_gpio_set_multiple()
488 guard(mutex)(&mcu->lock); in omnia_gpio_set_multiple()
502 if (gpio->feat_mask) in omnia_gpio_available()
503 return (mcu->features & gpio->feat_mask) == gpio->feat; in omnia_gpio_available()
505 if (gpio->feat) in omnia_gpio_available()
506 return mcu->features & gpio->feat; in omnia_gpio_available()
511 static int omnia_gpio_init_valid_mask(struct gpio_chip *gc, in omnia_gpio_init_valid_mask()
513 unsigned int ngpios) in omnia_gpio_init_valid_mask()
517 for (unsigned int i = 0; i < ngpios; i++) { in omnia_gpio_init_valid_mask()
520 if (gpio->cmd || is_int_bit_valid(gpio)) in omnia_gpio_init_valid_mask()
530 static int omnia_gpio_of_xlate(struct gpio_chip *gc, in omnia_gpio_of_xlate()
536 if (WARN_ON(gpiospec->args_count != 3)) in omnia_gpio_of_xlate()
537 return -EINVAL; in omnia_gpio_of_xlate()
540 *flags = gpiospec->args[2]; in omnia_gpio_of_xlate()
542 bank = gpiospec->args[0]; in omnia_gpio_of_xlate()
543 gpio = gpiospec->args[1]; in omnia_gpio_of_xlate()
547 return gpio < 16 ? gpio : -EINVAL; in omnia_gpio_of_xlate()
549 return gpio < 32 ? 16 + gpio : -EINVAL; in omnia_gpio_of_xlate()
551 return gpio < 16 ? 48 + gpio : -EINVAL; in omnia_gpio_of_xlate()
553 return -EINVAL; in omnia_gpio_of_xlate()
564 __clear_bit(bit, &mcu->rising); in omnia_irq_shutdown()
565 __clear_bit(bit, &mcu->falling); in omnia_irq_shutdown()
576 __clear_bit(bit, &mcu->rising); in omnia_irq_mask()
577 __clear_bit(bit, &mcu->mask); in omnia_irq_mask()
589 __set_bit(bit, &mcu->mask); in omnia_irq_unmask()
591 __set_bit(bit, &mcu->rising); in omnia_irq_unmask()
594 static int omnia_irq_set_type(struct irq_data *d, unsigned int type) in omnia_irq_set_type()
599 struct device *dev = &mcu->client->dev; in omnia_irq_set_type()
603 dev_err(dev, "irq %u: unsupported type %u\n", d->irq, type); in omnia_irq_set_type()
604 return -EINVAL; in omnia_irq_set_type()
607 __assign_bit(bit, &mcu->rising, type & IRQ_TYPE_EDGE_RISING); in omnia_irq_set_type()
608 __assign_bit(bit, &mcu->falling, type & IRQ_TYPE_EDGE_FALLING); in omnia_irq_set_type()
619 if (!(mcu->features & OMNIA_FEAT_NEW_INT_API)) in omnia_irq_bus_lock()
622 mutex_lock(&mcu->lock); in omnia_irq_bus_lock()
626 * omnia_mask_interleave - Interleaves the bytes from @rising and @falling
628 * @rising: rising mask
631 * Interleaves the little-endian bytes from @rising and @falling words.
633 * If @rising = (r0, r1, r2, r3) and @falling = (f0, f1, f2, f3), the result is
637 * this interleaved format. The rationale behind this is that the low-indexed
638 * bits are more important - in many cases, the user will be interested only in
640 * first 2 bytes (r0, f0), to save time on the slow I2C bus.
646 omnia_mask_interleave(u8 *dst, unsigned long rising, unsigned long falling) in omnia_mask_interleave() argument
648 for (unsigned int i = 0; i < sizeof(u32); i++) { in omnia_mask_interleave()
649 dst[2 * i] = rising >> (8 * i); in omnia_mask_interleave()
655 * omnia_mask_deinterleave - Deinterleaves the bytes into @rising and @falling
657 * @rising: pointer where to store the rising mask gathered from @src
662 static void omnia_mask_deinterleave(const u8 *src, unsigned long *rising, in omnia_mask_deinterleave() argument
665 *rising = *falling = 0; in omnia_mask_deinterleave()
667 for (unsigned int i = 0; i < sizeof(u32); i++) { in omnia_mask_deinterleave()
668 *rising |= src[2 * i] << (8 * i); in omnia_mask_deinterleave()
677 struct device *dev = &mcu->client->dev; in omnia_irq_bus_sync_unlock()
679 unsigned long rising, falling; in omnia_irq_bus_sync_unlock() local
680 int err; in omnia_irq_bus_sync_unlock()
683 if (!(mcu->features & OMNIA_FEAT_NEW_INT_API)) in omnia_irq_bus_sync_unlock()
688 rising = mcu->rising & mcu->mask; in omnia_irq_bus_sync_unlock()
689 falling = mcu->falling & mcu->mask; in omnia_irq_bus_sync_unlock()
691 /* interleave the rising and falling bytes into the command arguments */ in omnia_irq_bus_sync_unlock()
692 omnia_mask_interleave(&cmd[1], rising, falling); in omnia_irq_bus_sync_unlock()
694 dev_dbg(dev, "set int mask %8ph\n", &cmd[1]); in omnia_irq_bus_sync_unlock()
696 err = omnia_cmd_write(mcu->client, cmd, sizeof(cmd)); in omnia_irq_bus_sync_unlock()
703 * Remember which GPIOs have both rising and falling interrupts enabled. in omnia_irq_bus_sync_unlock()
708 mcu->both = rising & falling; in omnia_irq_bus_sync_unlock()
709 mcu->is_cached &= mcu->both; in omnia_irq_bus_sync_unlock()
712 mutex_unlock(&mcu->lock); in omnia_irq_bus_sync_unlock()
729 unsigned int ngpios) in omnia_irq_init_valid_mask()
733 for (unsigned int i = 0; i < ngpios; i++) { in omnia_irq_init_valid_mask()
744 static int omnia_irq_init_hw(struct gpio_chip *gc) in omnia_irq_init_hw()
751 return omnia_cmd_write(mcu->client, cmd, sizeof(cmd)); in omnia_irq_init_hw()
759 static unsigned int
760 omnia_irq_compute_pending_length(unsigned long rising, unsigned long falling) in omnia_irq_compute_pending_length() argument
762 return max(omnia_compute_reply_length(rising, true, 0), in omnia_irq_compute_pending_length()
769 struct device *dev = &mcu->client->dev; in omnia_irq_read_pending_new()
771 unsigned long rising, falling; in omnia_irq_read_pending_new() local
772 unsigned int len; in omnia_irq_read_pending_new()
773 int err; in omnia_irq_read_pending_new()
775 len = omnia_irq_compute_pending_length(mcu->rising & mcu->mask, in omnia_irq_read_pending_new()
776 mcu->falling & mcu->mask); in omnia_irq_read_pending_new()
780 guard(mutex)(&mcu->lock); in omnia_irq_read_pending_new()
782 err = omnia_cmd_read(mcu->client, OMNIA_CMD_GET_INT_AND_CLEAR, reply, in omnia_irq_read_pending_new()
789 /* deinterleave the reply bytes into rising and falling */ in omnia_irq_read_pending_new()
790 omnia_mask_deinterleave(reply, &rising, &falling); in omnia_irq_read_pending_new()
792 rising &= mcu->mask; in omnia_irq_read_pending_new()
793 falling &= mcu->mask; in omnia_irq_read_pending_new()
794 *pending = rising | falling; in omnia_irq_read_pending_new()
797 mcu->is_cached &= ~(rising & falling); in omnia_irq_read_pending_new()
798 mcu->is_cached |= mcu->both & (rising ^ falling); in omnia_irq_read_pending_new()
799 mcu->cached = (mcu->cached | rising) & ~falling; in omnia_irq_read_pending_new()
804 static int omnia_read_status_word_old_fw(struct omnia_mcu *mcu, in omnia_read_status_word_old_fw()
808 int err; in omnia_read_status_word_old_fw()
810 err = omnia_cmd_read_u16(mcu->client, OMNIA_CMD_GET_STATUS_WORD, in omnia_read_status_word_old_fw()
830 mcu->button_pressed_emul = false; in button_release_emul_fn()
831 generic_handle_irq_safe(mcu->client->irq); in button_release_emul_fn()
835 fill_int_from_sts(unsigned long *rising, unsigned long *falling, in fill_int_from_sts() argument
840 *rising |= int_bit; in fill_int_from_sts()
848 unsigned long status, rising_sts, falling_sts, rising, falling; in omnia_irq_read_pending_old() local
849 struct device *dev = &mcu->client->dev; in omnia_irq_read_pending_old()
850 int err; in omnia_irq_read_pending_old()
852 guard(mutex)(&mcu->lock); in omnia_irq_read_pending_old()
869 * - first we get an interrupt, we read the status word where in omnia_irq_read_pending_old()
871 * - MCU clears the OMNIA_STS_BUTTON_PRESSED bit because we read the in omnia_irq_read_pending_old()
873 * - we get another interrupt because the status word changed again in omnia_irq_read_pending_old()
876 * The gpiolib-cdev, gpiolib-sysfs and gpio-keys input driver all call in omnia_irq_read_pending_old()
885 mcu->button_pressed_emul = true; in omnia_irq_read_pending_old()
886 mod_delayed_work(system_wq, &mcu->button_release_emul_work, in omnia_irq_read_pending_old()
888 } else if (mcu->button_pressed_emul) { in omnia_irq_read_pending_old()
892 rising_sts = ~mcu->last_status & status; in omnia_irq_read_pending_old()
893 falling_sts = mcu->last_status & ~status; in omnia_irq_read_pending_old()
895 mcu->last_status = status; in omnia_irq_read_pending_old()
901 rising = 0; in omnia_irq_read_pending_old()
903 fill_int_from_sts(&rising, &falling, rising_sts, falling_sts, in omnia_irq_read_pending_old()
905 fill_int_from_sts(&rising, &falling, rising_sts, falling_sts, in omnia_irq_read_pending_old()
907 fill_int_from_sts(&rising, &falling, rising_sts, falling_sts, in omnia_irq_read_pending_old()
911 rising &= mcu->rising & mcu->mask; in omnia_irq_read_pending_old()
912 falling &= mcu->falling & mcu->mask; in omnia_irq_read_pending_old()
913 *pending = rising | falling; in omnia_irq_read_pending_old()
921 if (mcu->features & OMNIA_FEAT_NEW_INT_API) in omnia_irq_read_pending()
927 static irqreturn_t omnia_irq_thread_handler(int irq, void *dev_id) in omnia_irq_thread_handler()
932 unsigned int i; in omnia_irq_thread_handler()
937 domain = mcu->gc.irq.domain; in omnia_irq_thread_handler()
940 unsigned int nested_irq; in omnia_irq_thread_handler()
956 int val; in front_button_mode_show()
958 if (mcu->features & OMNIA_FEAT_NEW_INT_API) { in front_button_mode_show()
959 val = omnia_cmd_read_bit(mcu->client, OMNIA_CMD_GET_STATUS_WORD, in front_button_mode_show()
964 val = !!(mcu->last_status & OMNIA_STS_BUTTON_MODE); in front_button_mode_show()
975 int err, i; in front_button_mode_store()
1000 int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu) in omnia_mcu_register_gpiochip()
1002 bool new_api = mcu->features & OMNIA_FEAT_NEW_INT_API; in omnia_mcu_register_gpiochip()
1003 struct device *dev = &mcu->client->dev; in omnia_mcu_register_gpiochip()
1005 int err; in omnia_mcu_register_gpiochip()
1007 err = devm_mutex_init(dev, &mcu->lock); in omnia_mcu_register_gpiochip()
1011 mcu->gc.request = omnia_gpio_request; in omnia_mcu_register_gpiochip()
1012 mcu->gc.get_direction = omnia_gpio_get_direction; in omnia_mcu_register_gpiochip()
1013 mcu->gc.direction_input = omnia_gpio_direction_input; in omnia_mcu_register_gpiochip()
1014 mcu->gc.direction_output = omnia_gpio_direction_output; in omnia_mcu_register_gpiochip()
1015 mcu->gc.get = omnia_gpio_get; in omnia_mcu_register_gpiochip()
1016 mcu->gc.get_multiple = omnia_gpio_get_multiple; in omnia_mcu_register_gpiochip()
1017 mcu->gc.set = omnia_gpio_set; in omnia_mcu_register_gpiochip()
1018 mcu->gc.set_multiple = omnia_gpio_set_multiple; in omnia_mcu_register_gpiochip()
1019 mcu->gc.init_valid_mask = omnia_gpio_init_valid_mask; in omnia_mcu_register_gpiochip()
1020 mcu->gc.can_sleep = true; in omnia_mcu_register_gpiochip()
1021 mcu->gc.names = omnia_mcu_gpio_names; in omnia_mcu_register_gpiochip()
1022 mcu->gc.base = -1; in omnia_mcu_register_gpiochip()
1023 mcu->gc.ngpio = ARRAY_SIZE(omnia_gpios); in omnia_mcu_register_gpiochip()
1024 mcu->gc.label = "Turris Omnia MCU GPIOs"; in omnia_mcu_register_gpiochip()
1025 mcu->gc.parent = dev; in omnia_mcu_register_gpiochip()
1026 mcu->gc.owner = THIS_MODULE; in omnia_mcu_register_gpiochip()
1027 mcu->gc.of_gpio_n_cells = 3; in omnia_mcu_register_gpiochip()
1028 mcu->gc.of_xlate = omnia_gpio_of_xlate; in omnia_mcu_register_gpiochip()
1030 gpio_irq_chip_set_chip(&mcu->gc.irq, &omnia_mcu_irq_chip); in omnia_mcu_register_gpiochip()
1032 mcu->gc.irq.parent_handler = NULL; in omnia_mcu_register_gpiochip()
1033 mcu->gc.irq.num_parents = 0; in omnia_mcu_register_gpiochip()
1034 mcu->gc.irq.parents = NULL; in omnia_mcu_register_gpiochip()
1035 mcu->gc.irq.default_type = IRQ_TYPE_NONE; in omnia_mcu_register_gpiochip()
1036 mcu->gc.irq.handler = handle_bad_irq; in omnia_mcu_register_gpiochip()
1037 mcu->gc.irq.threaded = true; in omnia_mcu_register_gpiochip()
1039 mcu->gc.irq.init_hw = omnia_irq_init_hw; in omnia_mcu_register_gpiochip()
1040 mcu->gc.irq.init_valid_mask = omnia_irq_init_valid_mask; in omnia_mcu_register_gpiochip()
1042 err = devm_gpiochip_add_data(dev, &mcu->gc, mcu); in omnia_mcu_register_gpiochip()
1053 err = omnia_read_status_word_old_fw(mcu, &mcu->last_status); in omnia_mcu_register_gpiochip()
1058 INIT_DELAYED_WORK(&mcu->button_release_emul_work, in omnia_mcu_register_gpiochip()
1068 err = devm_request_threaded_irq(dev, mcu->client->irq, NULL, in omnia_mcu_register_gpiochip()
1070 "turris-omnia-mcu", mcu); in omnia_mcu_register_gpiochip()
1089 &mcu->button_release_emul_work); in omnia_mcu_register_gpiochip()