@ -52,6 +52,68 @@ static struct memory_type_mapping mem_type_mapping_tbl[] = {
{ " EXTLAST " , NULL , 0 , 0xFE } ,
} ;
static const struct of_device_id btmrvl_sdio_of_match_table [ ] = {
{ . compatible = " marvell,sd8897-bt " } ,
{ . compatible = " marvell,sd8997-bt " } ,
{ }
} ;
static irqreturn_t btmrvl_wake_irq_bt ( int irq , void * priv )
{
struct btmrvl_plt_wake_cfg * cfg = priv ;
if ( cfg - > irq_bt > = 0 ) {
pr_info ( " %s: wake by bt " , __func__ ) ;
cfg - > wake_by_bt = true ;
disable_irq_nosync ( irq ) ;
}
return IRQ_HANDLED ;
}
/* This function parses device tree node using mmc subnode devicetree API.
* The device node is saved in card - > plt_of_node .
* If the device tree node exists and includes interrupts attributes , this
* function will request platform specific wakeup interrupt .
*/
static int btmrvl_sdio_probe_of ( struct device * dev ,
struct btmrvl_sdio_card * card )
{
struct btmrvl_plt_wake_cfg * cfg ;
int ret ;
if ( ! dev - > of_node | |
! of_match_node ( btmrvl_sdio_of_match_table , dev - > of_node ) ) {
pr_err ( " sdio platform data not available " ) ;
return - 1 ;
}
card - > plt_of_node = dev - > of_node ;
card - > plt_wake_cfg = devm_kzalloc ( dev , sizeof ( * card - > plt_wake_cfg ) ,
GFP_KERNEL ) ;
cfg = card - > plt_wake_cfg ;
if ( cfg & & card - > plt_of_node ) {
cfg - > irq_bt = irq_of_parse_and_map ( card - > plt_of_node , 0 ) ;
if ( ! cfg - > irq_bt ) {
dev_err ( dev , " fail to parse irq_bt from device tree " ) ;
} else {
ret = devm_request_irq ( dev , cfg - > irq_bt ,
btmrvl_wake_irq_bt ,
IRQF_TRIGGER_LOW ,
" bt_wake " , cfg ) ;
if ( ret ) {
dev_err ( dev ,
" Failed to request irq_bt %d (%d) \n " ,
cfg - > irq_bt , ret ) ;
}
disable_irq ( cfg - > irq_bt ) ;
}
}
return 0 ;
}
/* The btmrvl_sdio_remove() callback function is called
* when user removes this module from kernel space or ejects
* the card from the slot . The driver handles these 2 cases
@ -1464,6 +1526,9 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
btmrvl_sdio_enable_host_int ( card ) ;
/* Device tree node parsing and platform specific configuration*/
btmrvl_sdio_probe_of ( & func - > dev , card ) ;
priv = btmrvl_add_card ( card ) ;
if ( ! priv ) {
BT_ERR ( " Initializing card failed! " ) ;
@ -1544,6 +1609,13 @@ static int btmrvl_sdio_suspend(struct device *dev)
return 0 ;
}
/* Enable platform specific wakeup interrupt */
if ( card - > plt_wake_cfg & & card - > plt_wake_cfg - > irq_bt > = 0 ) {
card - > plt_wake_cfg - > wake_by_bt = false ;
enable_irq ( card - > plt_wake_cfg - > irq_bt ) ;
enable_irq_wake ( card - > plt_wake_cfg - > irq_bt ) ;
}
priv = card - > priv ;
priv - > adapter - > is_suspending = true ;
hcidev = priv - > btmrvl_dev . hcidev ;
@ -1606,6 +1678,13 @@ static int btmrvl_sdio_resume(struct device *dev)
BT_DBG ( " %s: SDIO resume " , hcidev - > name ) ;
hci_resume_dev ( hcidev ) ;
/* Disable platform specific wakeup interrupt */
if ( card - > plt_wake_cfg & & card - > plt_wake_cfg - > irq_bt > = 0 ) {
disable_irq_wake ( card - > plt_wake_cfg - > irq_bt ) ;
if ( ! card - > plt_wake_cfg - > wake_by_bt )
disable_irq ( card - > plt_wake_cfg - > irq_bt ) ;
}
return 0 ;
}