Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: typec: tps6598x: Add support for polling interrupts status

Some development boards don't have the interrupt line connected.

In such cases we can resort to polling the interrupt status.

Signed-off-by: Aswath Govindraju <a-govindraju@ti.com>
Signed-off-by: Roger Quadros <rogerq@kernel.org>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20230324131853.41102-1-rogerq@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Aswath Govindraju and committed by
Greg Kroah-Hartman
0d6a119c 97318d64

+36 -5
+36 -5
drivers/usb/typec/tipd/core.c
··· 16 16 #include <linux/usb/typec.h> 17 17 #include <linux/usb/typec_altmode.h> 18 18 #include <linux/usb/role.h> 19 + #include <linux/workqueue.h> 19 20 20 21 #include "tps6598x.h" 21 22 #include "trace.h" ··· 98 97 99 98 int wakeup; 100 99 u16 pwr_status; 100 + struct delayed_work wq_poll; 101 + irq_handler_t irq_handler; 101 102 }; 102 103 103 104 static enum power_supply_property tps6598x_psy_props[] = { ··· 561 558 return IRQ_NONE; 562 559 } 563 560 561 + /* Time interval for Polling */ 562 + #define POLL_INTERVAL 500 /* msecs */ 563 + static void tps6598x_poll_work(struct work_struct *work) 564 + { 565 + struct tps6598x *tps = container_of(to_delayed_work(work), 566 + struct tps6598x, wq_poll); 567 + 568 + tps->irq_handler(0, tps); 569 + queue_delayed_work(system_power_efficient_wq, 570 + &tps->wq_poll, msecs_to_jiffies(POLL_INTERVAL)); 571 + } 572 + 564 573 static int tps6598x_check_mode(struct tps6598x *tps) 565 574 { 566 575 char mode[5] = { }; ··· 751 736 TPS_REG_INT_PLUG_EVENT; 752 737 } 753 738 739 + tps->irq_handler = irq_handler; 754 740 /* Make sure the controller has application firmware running */ 755 741 ret = tps6598x_check_mode(tps); 756 742 if (ret) ··· 843 827 dev_err(&client->dev, "failed to register partner\n"); 844 828 } 845 829 846 - ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, 847 - irq_handler, 848 - IRQF_SHARED | IRQF_ONESHOT, 849 - dev_name(&client->dev), tps); 830 + if (client->irq) { 831 + ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, 832 + irq_handler, 833 + IRQF_SHARED | IRQF_ONESHOT, 834 + dev_name(&client->dev), tps); 835 + } else { 836 + dev_warn(tps->dev, "Unable to find the interrupt, switching to polling\n"); 837 + INIT_DELAYED_WORK(&tps->wq_poll, tps6598x_poll_work); 838 + queue_delayed_work(system_power_efficient_wq, &tps->wq_poll, 839 + msecs_to_jiffies(POLL_INTERVAL)); 840 + } 841 + 850 842 if (ret) 851 843 goto err_disconnect; 852 844 ··· 862 838 fwnode_handle_put(fwnode); 863 839 864 840 tps->wakeup = device_property_read_bool(tps->dev, "wakeup-source"); 865 - if (tps->wakeup) { 841 + if (tps->wakeup && client->irq) { 866 842 device_init_wakeup(&client->dev, true); 867 843 enable_irq_wake(client->irq); 868 844 } ··· 901 877 enable_irq_wake(client->irq); 902 878 } 903 879 880 + if (!client->irq) 881 + cancel_delayed_work_sync(&tps->wq_poll); 882 + 904 883 return 0; 905 884 } 906 885 ··· 916 889 disable_irq_wake(client->irq); 917 890 enable_irq(client->irq); 918 891 } 892 + 893 + if (client->irq) 894 + queue_delayed_work(system_power_efficient_wq, &tps->wq_poll, 895 + msecs_to_jiffies(POLL_INTERVAL)); 919 896 920 897 return 0; 921 898 }