1717#include <linux/crc32.h>
1818#include <linux/string_helpers.h>
1919#include <linux/gpio/consumer.h>
20+ #include <linux/of_irq.h>
2021
2122#include <net/bluetooth/bluetooth.h>
2223#include <net/bluetooth/hci_core.h>
@@ -143,7 +144,9 @@ struct ps_data {
143144 bool driver_sent_cmd ;
144145 u16 h2c_ps_interval ;
145146 u16 c2h_ps_interval ;
147+ bool wakeup_source ;
146148 struct gpio_desc * h2c_ps_gpio ;
149+ s32 irq_handler ;
147150 struct hci_dev * hdev ;
148151 struct work_struct work ;
149152 struct timer_list ps_timer ;
@@ -476,12 +479,21 @@ static void ps_timeout_func(struct timer_list *t)
476479 }
477480}
478481
482+ static irqreturn_t ps_host_wakeup_irq_handler (int irq , void * priv )
483+ {
484+ struct btnxpuart_dev * nxpdev = (struct btnxpuart_dev * )priv ;
485+
486+ bt_dev_dbg (nxpdev -> hdev , "Host wakeup interrupt" );
487+ return IRQ_HANDLED ;
488+ }
479489static int ps_setup (struct hci_dev * hdev )
480490{
481491 struct btnxpuart_dev * nxpdev = hci_get_drvdata (hdev );
482492 struct serdev_device * serdev = nxpdev -> serdev ;
483493 struct ps_data * psdata = & nxpdev -> psdata ;
494+ int ret ;
484495
496+ /* Out-Of-Band Device Wakeup */
485497 psdata -> h2c_ps_gpio = devm_gpiod_get_optional (& serdev -> dev , "device-wakeup" ,
486498 GPIOD_OUT_LOW );
487499 if (IS_ERR (psdata -> h2c_ps_gpio )) {
@@ -493,11 +505,37 @@ static int ps_setup(struct hci_dev *hdev)
493505 if (device_property_read_u8 (& serdev -> dev , "nxp,wakein-pin" , & psdata -> h2c_wakeup_gpio )) {
494506 psdata -> h2c_wakeup_gpio = 0xff ; /* 0xff: use default pin/gpio */
495507 } else if (!psdata -> h2c_ps_gpio ) {
496- bt_dev_warn (hdev , "nxp,wakein-pin property without device-wakeup GPIO " );
508+ bt_dev_warn (hdev , "nxp,wakein-pin property without device-wakeup-gpios " );
497509 psdata -> h2c_wakeup_gpio = 0xff ;
498510 }
499511
500- device_property_read_u8 (& serdev -> dev , "nxp,wakeout-pin" , & psdata -> c2h_wakeup_gpio );
512+ /* Out-Of-Band Host Wakeup */
513+ if (of_property_read_bool (serdev -> dev .of_node , "wakeup-source" )) {
514+ psdata -> irq_handler = of_irq_get_byname (serdev -> dev .of_node , "wakeup" );
515+ bt_dev_info (nxpdev -> hdev , "irq_handler: %d" , psdata -> irq_handler );
516+ if (psdata -> irq_handler > 0 )
517+ psdata -> wakeup_source = true;
518+ }
519+
520+ if (device_property_read_u8 (& serdev -> dev , "nxp,wakeout-pin" , & psdata -> c2h_wakeup_gpio )) {
521+ psdata -> c2h_wakeup_gpio = 0xff ;
522+ if (psdata -> wakeup_source ) {
523+ bt_dev_warn (hdev , "host wakeup interrupt without nxp,wakeout-pin" );
524+ psdata -> wakeup_source = false;
525+ }
526+ } else if (!psdata -> wakeup_source ) {
527+ bt_dev_warn (hdev , "nxp,wakeout-pin property without host wakeup interrupt" );
528+ psdata -> c2h_wakeup_gpio = 0xff ;
529+ }
530+
531+ if (psdata -> wakeup_source ) {
532+ ret = devm_request_irq (& serdev -> dev , psdata -> irq_handler ,
533+ ps_host_wakeup_irq_handler ,
534+ IRQF_ONESHOT | IRQF_TRIGGER_FALLING ,
535+ dev_name (& serdev -> dev ), nxpdev );
536+ disable_irq (psdata -> irq_handler );
537+ device_init_wakeup (& serdev -> dev , true);
538+ }
501539
502540 psdata -> hdev = hdev ;
503541 INIT_WORK (& psdata -> work , ps_work_func );
@@ -637,12 +675,10 @@ static void ps_init(struct hci_dev *hdev)
637675
638676 psdata -> ps_state = PS_STATE_AWAKE ;
639677
640- if (psdata -> c2h_wakeup_gpio ) {
678+ if (psdata -> c2h_wakeup_gpio != 0xff )
641679 psdata -> c2h_wakeupmode = BT_HOST_WAKEUP_METHOD_GPIO ;
642- } else {
680+ else
643681 psdata -> c2h_wakeupmode = BT_HOST_WAKEUP_METHOD_NONE ;
644- psdata -> c2h_wakeup_gpio = 0xff ;
645- }
646682
647683 psdata -> cur_h2c_wakeupmode = WAKEUP_METHOD_INVALID ;
648684 if (psdata -> h2c_ps_gpio )
@@ -1821,6 +1857,11 @@ static int nxp_serdev_suspend(struct device *dev)
18211857 struct ps_data * psdata = & nxpdev -> psdata ;
18221858
18231859 ps_control (psdata -> hdev , PS_STATE_SLEEP );
1860+
1861+ if (psdata -> wakeup_source ) {
1862+ enable_irq_wake (psdata -> irq_handler );
1863+ enable_irq (psdata -> irq_handler );
1864+ }
18241865 return 0 ;
18251866}
18261867
@@ -1829,6 +1870,11 @@ static int nxp_serdev_resume(struct device *dev)
18291870 struct btnxpuart_dev * nxpdev = dev_get_drvdata (dev );
18301871 struct ps_data * psdata = & nxpdev -> psdata ;
18311872
1873+ if (psdata -> wakeup_source ) {
1874+ disable_irq (psdata -> irq_handler );
1875+ disable_irq_wake (psdata -> irq_handler );
1876+ }
1877+
18321878 ps_control (psdata -> hdev , PS_STATE_AWAKE );
18331879 return 0 ;
18341880}
0 commit comments