diff options
author | Li Jun <b47624@freescale.com> | 2014-06-29 12:43:02 +0800 |
---|---|---|
committer | Li Jun <B47624@freescale.com> | 2014-06-30 16:37:44 +0800 |
commit | 0b2b7c9b4005035cb7e62520c4d87a76004aea07 (patch) | |
tree | 2f8e86c30607dfe179aa2fb350f07861706d2c3f | |
parent | 91d9685df8f456cead12dda23849c2e0cbada83f (diff) |
ENGR00320439-8 usb: chipidea: otg_fsm: power lost handling for otg fsm
This patch adds support for system resume from power lost in otg fsm mode.
Signed-off-by: Li Jun <b47624@freescale.com>
-rw-r--r-- | drivers/usb/chipidea/core.c | 5 | ||||
-rw-r--r-- | drivers/usb/chipidea/otg_fsm.c | 37 | ||||
-rw-r--r-- | drivers/usb/chipidea/otg_fsm.h | 6 |
3 files changed, 47 insertions, 1 deletions
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index c1350e7e7553..b6c57161985c 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -649,7 +649,10 @@ static void ci_power_lost_work(struct work_struct *work) power_lost_work); pm_runtime_get_sync(ci->dev); - ci_start_new_role(ci); + if (ci_otg_is_fsm_mode(ci)) + ci_hdrc_otg_fsm_restart(ci); + else + ci_start_new_role(ci); pm_runtime_put_sync(ci->dev); enable_irq(ci->irq); } diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c index bf85469993f2..6faab2a06053 100644 --- a/drivers/usb/chipidea/otg_fsm.c +++ b/drivers/usb/chipidea/otg_fsm.c @@ -29,6 +29,7 @@ #include "bits.h" #include "otg.h" #include "otg_fsm.h" +#include "host.h" static struct ci_otg_fsm_timer *otg_timer_initializer (struct ci_hdrc *ci, void (*function)(void *, unsigned long), @@ -899,3 +900,39 @@ void ci_hdrc_otg_fsm_remove(struct ci_hdrc *ci) sysfs_remove_group(&ci->dev->kobj, &inputs_attr_group); del_timer_sync(&ci->hnp_polling_timer); } + +/* Restart OTG fsm if resume from power lost */ +void ci_hdrc_otg_fsm_restart(struct ci_hdrc *ci) +{ + struct otg_fsm *fsm = &ci->fsm; + int id_status = fsm->id; + + /* Update fsm if power lost in peripheral state */ + if (ci->transceiver->state == OTG_STATE_B_PERIPHERAL) { + fsm->b_sess_vld = 0; + otg_statemachine(fsm); + } + + hw_write_otgsc(ci, OTGSC_IDIE, OTGSC_IDIE); + hw_write_otgsc(ci, OTGSC_AVVIE, OTGSC_AVVIE); + + /* Update fsm variables for restart */ + fsm->id = hw_read_otgsc(ci, OTGSC_ID) ? 1 : 0; + if (fsm->id) { + fsm->b_ssend_srp = + hw_read_otgsc(ci, OTGSC_BSV) ? 0 : 1; + fsm->b_sess_vld = + hw_read_otgsc(ci, OTGSC_BSV) ? 1 : 0; + } else if (fsm->id != id_status) { + /* ID changes to be 0 */ + fsm->a_bus_drop = 0; + fsm->a_bus_req = 1; + ci->id_event = true; + } + + if (ci_hdrc_host_has_device(ci) && + !hw_read(ci, OP_PORTSC, PORTSC_CCS)) + fsm->b_conn = 0; + + ci_otg_fsm_work(ci); +} diff --git a/drivers/usb/chipidea/otg_fsm.h b/drivers/usb/chipidea/otg_fsm.h index 2cfffb7061e1..3399e901b419 100644 --- a/drivers/usb/chipidea/otg_fsm.h +++ b/drivers/usb/chipidea/otg_fsm.h @@ -98,6 +98,7 @@ int ci_otg_fsm_work(struct ci_hdrc *ci); irqreturn_t ci_otg_fsm_irq(struct ci_hdrc *ci); void ci_hdrc_otg_fsm_start(struct ci_hdrc *ci); void ci_hdrc_otg_fsm_remove(struct ci_hdrc *ci); +void ci_hdrc_otg_fsm_restart(struct ci_hdrc *ci); #else @@ -126,6 +127,11 @@ static inline void ci_hdrc_otg_fsm_remove(struct ci_hdrc *ci) } +static inline void ci_hdrc_otg_fsm_restart(struct ci_hdrc *ci) +{ + +} + #endif #endif /* __DRIVERS_USB_CHIPIDEA_OTG_FSM_H */ |