2010-04-08 22:16:55 +04:00
/*
* Shared Transport driver
* HCI - LL module responsible for TI proprietary HCI_LL protocol
2010-10-06 20:18:14 +04:00
* Copyright ( C ) 2009 - 2010 Texas Instruments
* Author : Pavan Savoy < pavan_savoy @ ti . com >
2010-04-08 22:16:55 +04:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*
*/
# define pr_fmt(fmt) "(stll) :" fmt
2010-09-17 20:06:11 +04:00
# include <linux/skbuff.h>
# include <linux/module.h>
2010-10-01 00:13:30 +04:00
# include <linux/ti_wilink_st.h>
2010-04-08 22:16:55 +04:00
/**********************************************************************/
/* internal functions */
static void send_ll_cmd ( struct st_data_s * st_data ,
unsigned char cmd )
{
2011-02-04 11:23:12 +03:00
pr_debug ( " %s: writing %x " , __func__ , cmd ) ;
2010-04-08 22:16:55 +04:00
st_int_write ( st_data , & cmd , 1 ) ;
return ;
}
static void ll_device_want_to_sleep ( struct st_data_s * st_data )
{
2010-07-22 14:32:05 +04:00
pr_debug ( " %s " , __func__ ) ;
2010-04-08 22:16:55 +04:00
/* sanity check */
if ( st_data - > ll_state ! = ST_LL_AWAKE )
pr_err ( " ERR hcill: ST_LL_GO_TO_SLEEP_IND "
" in state %ld " , st_data - > ll_state ) ;
send_ll_cmd ( st_data , LL_SLEEP_ACK ) ;
/* update state */
st_data - > ll_state = ST_LL_ASLEEP ;
}
static void ll_device_want_to_wakeup ( struct st_data_s * st_data )
{
/* diff actions in diff states */
switch ( st_data - > ll_state ) {
case ST_LL_ASLEEP :
send_ll_cmd ( st_data , LL_WAKE_UP_ACK ) ; /* send wake_ack */
break ;
case ST_LL_ASLEEP_TO_AWAKE :
/* duplicate wake_ind */
pr_err ( " duplicate wake_ind while waiting for Wake ack " ) ;
break ;
case ST_LL_AWAKE :
/* duplicate wake_ind */
pr_err ( " duplicate wake_ind already AWAKE " ) ;
break ;
case ST_LL_AWAKE_TO_ASLEEP :
/* duplicate wake_ind */
pr_err ( " duplicate wake_ind " ) ;
break ;
}
/* update state */
st_data - > ll_state = ST_LL_AWAKE ;
}
/**********************************************************************/
/* functions invoked by ST Core */
/* called when ST Core wants to
* enable ST LL */
void st_ll_enable ( struct st_data_s * ll )
{
ll - > ll_state = ST_LL_AWAKE ;
}
/* called when ST Core /local module wants to
* disable ST LL */
void st_ll_disable ( struct st_data_s * ll )
{
ll - > ll_state = ST_LL_INVALID ;
}
/* called when ST Core wants to update the state */
void st_ll_wakeup ( struct st_data_s * ll )
{
if ( likely ( ll - > ll_state ! = ST_LL_AWAKE ) ) {
send_ll_cmd ( ll , LL_WAKE_UP_IND ) ; /* WAKE_IND */
ll - > ll_state = ST_LL_ASLEEP_TO_AWAKE ;
} else {
/* don't send the duplicate wake_indication */
pr_err ( " Chip already AWAKE " ) ;
}
}
/* called when ST Core wants the state */
unsigned long st_ll_getstate ( struct st_data_s * ll )
{
2010-07-22 14:32:05 +04:00
pr_debug ( " returning state %ld " , ll - > ll_state ) ;
2010-04-08 22:16:55 +04:00
return ll - > ll_state ;
}
/* called from ST Core, when a PM related packet arrives */
unsigned long st_ll_sleep_state ( struct st_data_s * st_data ,
unsigned char cmd )
{
switch ( cmd ) {
case LL_SLEEP_IND : /* sleep ind */
2011-02-04 11:23:12 +03:00
pr_debug ( " sleep indication recvd " ) ;
2010-04-08 22:16:55 +04:00
ll_device_want_to_sleep ( st_data ) ;
break ;
case LL_SLEEP_ACK : /* sleep ack */
pr_err ( " sleep ack rcvd: host shouldn't " ) ;
break ;
case LL_WAKE_UP_IND : /* wake ind */
2011-02-04 11:23:12 +03:00
pr_debug ( " wake indication recvd " ) ;
2010-04-08 22:16:55 +04:00
ll_device_want_to_wakeup ( st_data ) ;
break ;
case LL_WAKE_UP_ACK : /* wake ack */
2011-02-04 11:23:12 +03:00
pr_debug ( " wake ack rcvd " ) ;
2010-04-08 22:16:55 +04:00
st_data - > ll_state = ST_LL_AWAKE ;
break ;
default :
pr_err ( " unknown input/state " ) ;
2011-02-04 11:23:11 +03:00
return - EINVAL ;
2010-04-08 22:16:55 +04:00
}
2010-07-14 17:21:12 +04:00
return 0 ;
2010-04-08 22:16:55 +04:00
}
/* Called from ST CORE to initialize ST LL */
long st_ll_init ( struct st_data_s * ll )
{
/* set state to invalid */
ll - > ll_state = ST_LL_INVALID ;
return 0 ;
}
/* Called from ST CORE to de-initialize ST LL */
long st_ll_deinit ( struct st_data_s * ll )
{
return 0 ;
}