Lines Matching full:mcu
3 * CZ.NIC's Turris Omnia MCU GPIO and IRQ driver
26 #include <linux/turris-omnia-mcu-interface.h>
27 #include "turris-omnia-mcu.h"
234 static int omnia_ctl_cmd_locked(struct omnia_mcu *mcu, u8 cmd, u16 val, u16 mask) in omnia_ctl_cmd_locked() argument
258 return omnia_cmd_write(mcu->client, buf, len); in omnia_ctl_cmd_locked()
261 static int omnia_ctl_cmd(struct omnia_mcu *mcu, u8 cmd, u16 val, u16 mask) in omnia_ctl_cmd() argument
263 guard(mutex)(&mcu->lock); in omnia_ctl_cmd()
265 return omnia_ctl_cmd_locked(mcu, cmd, val, mask); in omnia_ctl_cmd()
278 struct omnia_mcu *mcu = gpiochip_get_data(gc); in omnia_gpio_get_direction() local
283 scoped_guard(mutex, &mcu->lock) { in omnia_gpio_get_direction()
284 val = omnia_cmd_read_bit(mcu->client, in omnia_gpio_get_direction()
306 struct omnia_mcu *mcu = gpiochip_get_data(gc); in omnia_gpio_direction_input() local
309 return omnia_ctl_cmd(mcu, OMNIA_CMD_EXT_CONTROL, in omnia_gpio_direction_input()
323 struct omnia_mcu *mcu = gpiochip_get_data(gc); in omnia_gpio_direction_output() local
335 return omnia_ctl_cmd(mcu, gpio->ctl_cmd, val, mask); in omnia_gpio_direction_output()
341 struct omnia_mcu *mcu = gpiochip_get_data(gc); in omnia_gpio_get() local
345 * of every change of the status word by an interrupt from MCU and save in omnia_gpio_get()
350 !(mcu->features & OMNIA_FEAT_NEW_INT_API)) in omnia_gpio_get()
351 return test_bit(gpio->bit, &mcu->last_status); in omnia_gpio_get()
353 guard(mutex)(&mcu->lock); in omnia_gpio_get()
360 if (is_int_bit_valid(gpio) && test_bit(gpio->int_bit, &mcu->is_cached)) in omnia_gpio_get()
361 return test_bit(gpio->int_bit, &mcu->cached); in omnia_gpio_get()
363 return omnia_cmd_read_bit(mcu->client, gpio->cmd, BIT(gpio->bit)); in omnia_gpio_get()
386 struct omnia_mcu *mcu = gpiochip_get_data(gc); in omnia_gpio_get_multiple() local
387 struct i2c_client *client = mcu->client; in omnia_gpio_get_multiple()
401 guard(mutex)(&mcu->lock); in omnia_gpio_get_multiple()
403 if (mcu->features & OMNIA_FEAT_NEW_INT_API) { in omnia_gpio_get_multiple()
414 sts = mcu->last_status; in omnia_gpio_get_multiple()
445 struct omnia_mcu *mcu = gpiochip_get_data(gc); in omnia_gpio_set() local
454 omnia_ctl_cmd(mcu, gpio->ctl_cmd, val, mask); in omnia_gpio_set()
461 struct omnia_mcu *mcu = gpiochip_get_data(gc); in omnia_gpio_set_multiple() local
489 guard(mutex)(&mcu->lock); in omnia_gpio_set_multiple()
492 omnia_ctl_cmd_locked(mcu, OMNIA_CMD_GENERAL_CONTROL, in omnia_gpio_set_multiple()
496 omnia_ctl_cmd_locked(mcu, OMNIA_CMD_EXT_CONTROL, in omnia_gpio_set_multiple()
500 static bool omnia_gpio_available(struct omnia_mcu *mcu, in omnia_gpio_available() argument
504 return (mcu->features & gpio->feat_mask) == gpio->feat; in omnia_gpio_available()
507 return mcu->features & gpio->feat; in omnia_gpio_available()
516 struct omnia_mcu *mcu = gpiochip_get_data(gc); in omnia_gpio_init_valid_mask() local
523 omnia_gpio_available(mcu, gpio)); in omnia_gpio_init_valid_mask()
561 struct omnia_mcu *mcu = gpiochip_get_data(gc); in omnia_irq_shutdown() local
565 __clear_bit(bit, &mcu->rising); in omnia_irq_shutdown()
566 __clear_bit(bit, &mcu->falling); in omnia_irq_shutdown()
572 struct omnia_mcu *mcu = gpiochip_get_data(gc); in omnia_irq_mask() local
577 __clear_bit(bit, &mcu->rising); in omnia_irq_mask()
578 __clear_bit(bit, &mcu->mask); in omnia_irq_mask()
585 struct omnia_mcu *mcu = gpiochip_get_data(gc); in omnia_irq_unmask() local
590 __set_bit(bit, &mcu->mask); in omnia_irq_unmask()
592 __set_bit(bit, &mcu->rising); in omnia_irq_unmask()
598 struct omnia_mcu *mcu = gpiochip_get_data(gc); in omnia_irq_set_type() local
600 struct device *dev = &mcu->client->dev; in omnia_irq_set_type()
608 __assign_bit(bit, &mcu->rising, type & IRQ_TYPE_EDGE_RISING); in omnia_irq_set_type()
609 __assign_bit(bit, &mcu->falling, type & IRQ_TYPE_EDGE_FALLING); in omnia_irq_set_type()
617 struct omnia_mcu *mcu = gpiochip_get_data(gc); in omnia_irq_bus_lock() local
619 /* nothing to do if MCU firmware does not support new interrupt API */ in omnia_irq_bus_lock()
620 if (!(mcu->features & OMNIA_FEAT_NEW_INT_API)) in omnia_irq_bus_lock()
623 mutex_lock(&mcu->lock); in omnia_irq_bus_lock()
637 * The MCU receives an interrupt mask and reports a pending interrupt bitmap in
677 struct omnia_mcu *mcu = gpiochip_get_data(gc); in omnia_irq_bus_sync_unlock() local
678 struct device *dev = &mcu->client->dev; in omnia_irq_bus_sync_unlock()
683 /* nothing to do if MCU firmware does not support new interrupt API */ in omnia_irq_bus_sync_unlock()
684 if (!(mcu->features & OMNIA_FEAT_NEW_INT_API)) in omnia_irq_bus_sync_unlock()
689 rising = mcu->rising & mcu->mask; in omnia_irq_bus_sync_unlock()
690 falling = mcu->falling & mcu->mask; in omnia_irq_bus_sync_unlock()
697 err = omnia_cmd_write(mcu->client, cmd, sizeof(cmd)); in omnia_irq_bus_sync_unlock()
709 mcu->both = rising & falling; in omnia_irq_bus_sync_unlock()
710 mcu->is_cached &= mcu->both; in omnia_irq_bus_sync_unlock()
713 mutex_unlock(&mcu->lock); in omnia_irq_bus_sync_unlock()
717 .name = "Turris Omnia MCU interrupts",
732 struct omnia_mcu *mcu = gpiochip_get_data(gc); in omnia_irq_init_valid_mask() local
739 omnia_gpio_available(mcu, gpio)); in omnia_irq_init_valid_mask()
747 struct omnia_mcu *mcu = gpiochip_get_data(gc); in omnia_irq_init_hw() local
752 return omnia_cmd_write(mcu->client, cmd, sizeof(cmd)); in omnia_irq_init_hw()
767 static bool omnia_irq_read_pending_new(struct omnia_mcu *mcu, in omnia_irq_read_pending_new() argument
770 struct device *dev = &mcu->client->dev; in omnia_irq_read_pending_new()
776 len = omnia_irq_compute_pending_length(mcu->rising & mcu->mask, in omnia_irq_read_pending_new()
777 mcu->falling & mcu->mask); in omnia_irq_read_pending_new()
781 guard(mutex)(&mcu->lock); in omnia_irq_read_pending_new()
783 err = omnia_cmd_read(mcu->client, OMNIA_CMD_GET_INT_AND_CLEAR, reply, in omnia_irq_read_pending_new()
793 rising &= mcu->mask; in omnia_irq_read_pending_new()
794 falling &= mcu->mask; in omnia_irq_read_pending_new()
798 mcu->is_cached &= ~(rising & falling); in omnia_irq_read_pending_new()
799 mcu->is_cached |= mcu->both & (rising ^ falling); in omnia_irq_read_pending_new()
800 mcu->cached = (mcu->cached | rising) & ~falling; in omnia_irq_read_pending_new()
805 static int omnia_read_status_word_old_fw(struct omnia_mcu *mcu, in omnia_read_status_word_old_fw() argument
811 err = omnia_cmd_read_u16(mcu->client, OMNIA_CMD_GET_STATUS_WORD, in omnia_read_status_word_old_fw()
827 struct omnia_mcu *mcu = container_of(to_delayed_work(work), in button_release_emul_fn() local
831 mcu->button_pressed_emul = false; in button_release_emul_fn()
832 generic_handle_irq_safe(mcu->client->irq); in button_release_emul_fn()
846 static bool omnia_irq_read_pending_old(struct omnia_mcu *mcu, in omnia_irq_read_pending_old() argument
850 struct device *dev = &mcu->client->dev; in omnia_irq_read_pending_old()
853 guard(mutex)(&mcu->lock); in omnia_irq_read_pending_old()
855 err = omnia_read_status_word_old_fw(mcu, &status); in omnia_irq_read_pending_old()
872 * - MCU clears the OMNIA_STS_BUTTON_PRESSED bit because we read the in omnia_irq_read_pending_old()
886 mcu->button_pressed_emul = true; in omnia_irq_read_pending_old()
887 mod_delayed_work(system_wq, &mcu->button_release_emul_work, in omnia_irq_read_pending_old()
889 } else if (mcu->button_pressed_emul) { in omnia_irq_read_pending_old()
893 rising_sts = ~mcu->last_status & status; in omnia_irq_read_pending_old()
894 falling_sts = mcu->last_status & ~status; in omnia_irq_read_pending_old()
896 mcu->last_status = status; in omnia_irq_read_pending_old()
912 rising &= mcu->rising & mcu->mask; in omnia_irq_read_pending_old()
913 falling &= mcu->falling & mcu->mask; in omnia_irq_read_pending_old()
919 static bool omnia_irq_read_pending(struct omnia_mcu *mcu, in omnia_irq_read_pending() argument
922 if (mcu->features & OMNIA_FEAT_NEW_INT_API) in omnia_irq_read_pending()
923 return omnia_irq_read_pending_new(mcu, pending); in omnia_irq_read_pending()
925 return omnia_irq_read_pending_old(mcu, pending); in omnia_irq_read_pending()
930 struct omnia_mcu *mcu = dev_id; in omnia_irq_thread_handler() local
935 if (!omnia_irq_read_pending(mcu, &pending)) in omnia_irq_thread_handler()
938 domain = mcu->gc.irq.domain; in omnia_irq_thread_handler()
951 static const char * const front_button_modes[] = { "mcu", "cpu" };
956 struct omnia_mcu *mcu = dev_get_drvdata(dev); in front_button_mode_show() local
959 if (mcu->features & OMNIA_FEAT_NEW_INT_API) { in front_button_mode_show()
960 val = omnia_cmd_read_bit(mcu->client, OMNIA_CMD_GET_STATUS_WORD, in front_button_mode_show()
965 val = !!(mcu->last_status & OMNIA_STS_BUTTON_MODE); in front_button_mode_show()
975 struct omnia_mcu *mcu = dev_get_drvdata(dev); in front_button_mode_store() local
982 err = omnia_ctl_cmd_locked(mcu, OMNIA_CMD_GENERAL_CONTROL, in front_button_mode_store()
1001 int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu) in omnia_mcu_register_gpiochip() argument
1003 bool new_api = mcu->features & OMNIA_FEAT_NEW_INT_API; in omnia_mcu_register_gpiochip()
1004 struct device *dev = &mcu->client->dev; in omnia_mcu_register_gpiochip()
1008 err = devm_mutex_init(dev, &mcu->lock); in omnia_mcu_register_gpiochip()
1012 mcu->gc.request = omnia_gpio_request; in omnia_mcu_register_gpiochip()
1013 mcu->gc.get_direction = omnia_gpio_get_direction; in omnia_mcu_register_gpiochip()
1014 mcu->gc.direction_input = omnia_gpio_direction_input; in omnia_mcu_register_gpiochip()
1015 mcu->gc.direction_output = omnia_gpio_direction_output; in omnia_mcu_register_gpiochip()
1016 mcu->gc.get = omnia_gpio_get; in omnia_mcu_register_gpiochip()
1017 mcu->gc.get_multiple = omnia_gpio_get_multiple; in omnia_mcu_register_gpiochip()
1018 mcu->gc.set = omnia_gpio_set; in omnia_mcu_register_gpiochip()
1019 mcu->gc.set_multiple = omnia_gpio_set_multiple; in omnia_mcu_register_gpiochip()
1020 mcu->gc.init_valid_mask = omnia_gpio_init_valid_mask; in omnia_mcu_register_gpiochip()
1021 mcu->gc.can_sleep = true; in omnia_mcu_register_gpiochip()
1022 mcu->gc.names = omnia_mcu_gpio_names; in omnia_mcu_register_gpiochip()
1023 mcu->gc.base = -1; in omnia_mcu_register_gpiochip()
1024 mcu->gc.ngpio = ARRAY_SIZE(omnia_gpios); in omnia_mcu_register_gpiochip()
1025 mcu->gc.label = "Turris Omnia MCU GPIOs"; in omnia_mcu_register_gpiochip()
1026 mcu->gc.parent = dev; in omnia_mcu_register_gpiochip()
1027 mcu->gc.owner = THIS_MODULE; in omnia_mcu_register_gpiochip()
1028 mcu->gc.of_gpio_n_cells = 3; in omnia_mcu_register_gpiochip()
1029 mcu->gc.of_xlate = omnia_gpio_of_xlate; in omnia_mcu_register_gpiochip()
1031 gpio_irq_chip_set_chip(&mcu->gc.irq, &omnia_mcu_irq_chip); in omnia_mcu_register_gpiochip()
1033 mcu->gc.irq.parent_handler = NULL; in omnia_mcu_register_gpiochip()
1034 mcu->gc.irq.num_parents = 0; in omnia_mcu_register_gpiochip()
1035 mcu->gc.irq.parents = NULL; in omnia_mcu_register_gpiochip()
1036 mcu->gc.irq.default_type = IRQ_TYPE_NONE; in omnia_mcu_register_gpiochip()
1037 mcu->gc.irq.handler = handle_bad_irq; in omnia_mcu_register_gpiochip()
1038 mcu->gc.irq.threaded = true; in omnia_mcu_register_gpiochip()
1040 mcu->gc.irq.init_hw = omnia_irq_init_hw; in omnia_mcu_register_gpiochip()
1041 mcu->gc.irq.init_valid_mask = omnia_irq_init_valid_mask; in omnia_mcu_register_gpiochip()
1043 err = devm_gpiochip_add_data(dev, &mcu->gc, mcu); in omnia_mcu_register_gpiochip()
1054 err = omnia_read_status_word_old_fw(mcu, &mcu->last_status); in omnia_mcu_register_gpiochip()
1059 INIT_DELAYED_WORK(&mcu->button_release_emul_work, in omnia_mcu_register_gpiochip()
1069 err = devm_request_threaded_irq(dev, mcu->client->irq, NULL, in omnia_mcu_register_gpiochip()
1071 "turris-omnia-mcu", mcu); in omnia_mcu_register_gpiochip()
1090 &mcu->button_release_emul_work); in omnia_mcu_register_gpiochip()
1098 int omnia_mcu_request_irq(struct omnia_mcu *mcu, u32 spec, in omnia_mcu_request_irq() argument
1108 irq = gpiod_to_irq(gpio_device_get_desc(mcu->gc.gpiodev, irq_idx)); in omnia_mcu_request_irq()
1112 return devm_request_threaded_irq(&mcu->client->dev, irq, NULL, in omnia_mcu_request_irq()
1113 thread_fn, IRQF_ONESHOT, devname, mcu); in omnia_mcu_request_irq()