summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorLi Jun <b47624@freescale.com>2014-06-23 16:11:12 +0800
committerLi Jun <B47624@freescale.com>2014-06-26 16:50:40 +0800
commitf3dd2721c55fe5777ee2ba1e8c8317058a24173f (patch)
tree54304dec3775908d09d74db120a9816bfb2f0f3c /drivers/usb
parentbc88a95b09a1b9aecbe0c1e21a04abf6c0821b4e (diff)
ENGR00319720-6 usb: chipidea: otg_fsm: add HNP polling support
This patch adds HNP polling support for chipidea otg fsm driver, which adds a SW timer to send HNP polling request. Signed-off-by: Li Jun <b47624@freescale.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/chipidea/ci.h2
-rw-r--r--drivers/usb/chipidea/otg_fsm.c33
-rw-r--r--drivers/usb/chipidea/otg_fsm.h2
3 files changed, 35 insertions, 2 deletions
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index cbd333edbec0..a52f9d38dc89 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -154,6 +154,8 @@ struct ci_hdrc {
bool is_otg;
struct otg_fsm fsm;
struct ci_otg_fsm_timer_list *fsm_timer;
+ struct timer_list hnp_polling_timer;
+ bool hnp_polling_req;
struct work_struct work;
struct workqueue_struct *wq;
diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c
index fc9d865d0f25..59454bfadf06 100644
--- a/drivers/usb/chipidea/otg_fsm.c
+++ b/drivers/usb/chipidea/otg_fsm.c
@@ -369,6 +369,14 @@ static void b_data_pulse_end(void *ptr, unsigned long indicator)
ci_otg_queue_work(ci);
}
+static void hnp_polling_timer_work(unsigned long arg)
+{
+ struct ci_hdrc *ci = (struct ci_hdrc *)arg;
+
+ ci->hnp_polling_req = true;
+ ci_otg_queue_work(ci);
+}
+
/* Initialize timers */
static int ci_otg_init_timers(struct ci_hdrc *ci)
{
@@ -439,9 +447,17 @@ static int ci_otg_init_timers(struct ci_hdrc *ci)
if (ci->fsm_timer->timer_list[B_SESS_VLD] == NULL)
return -ENOMEM;
+ setup_timer(&ci->hnp_polling_timer, hnp_polling_timer_work,
+ (unsigned long)ci);
return 0;
}
+static void ci_otg_add_hnp_polling_timer(struct ci_hdrc *ci)
+{
+ mod_timer(&ci->hnp_polling_timer,
+ jiffies + msecs_to_jiffies(T_HOST_REQ_POLL));
+}
+
/* -------------------------------------------------------------*/
/* Operations that will be called from OTG Finite State Machine */
/* -------------------------------------------------------------*/
@@ -449,8 +465,12 @@ static void ci_otg_fsm_add_timer(struct otg_fsm *fsm, enum otg_fsm_timer t)
{
struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm);
- if (t < NUM_OTG_FSM_TIMERS)
- ci_otg_add_timer(ci, t);
+ if (t < NUM_OTG_FSM_TIMERS) {
+ if (t == HNP_POLLING)
+ ci_otg_add_hnp_polling_timer(ci);
+ else
+ ci_otg_add_timer(ci, t);
+ }
return;
}
@@ -605,6 +625,14 @@ int ci_otg_fsm_work(struct ci_hdrc *ci)
}
pm_runtime_get_sync(ci->dev);
+ if (ci->hnp_polling_req) {
+ ci->hnp_polling_req = false;
+ if (otg_hnp_polling(&ci->fsm) != HOST_REQUEST_FLAG) {
+ pm_runtime_put_sync(ci->dev);
+ return 0;
+ }
+ }
+
if (otg_statemachine(&ci->fsm)) {
if (ci->transceiver->state == OTG_STATE_A_IDLE) {
/*
@@ -863,4 +891,5 @@ int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci)
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);
}
diff --git a/drivers/usb/chipidea/otg_fsm.h b/drivers/usb/chipidea/otg_fsm.h
index 94c085f456a9..2cfffb7061e1 100644
--- a/drivers/usb/chipidea/otg_fsm.h
+++ b/drivers/usb/chipidea/otg_fsm.h
@@ -64,6 +64,8 @@
#define TB_SESS_VLD (1000)
+#define T_HOST_REQ_POLL (1500) /* HNP polling interval 1s~2s */
+
enum ci_otg_fsm_timer_index {
/*
* CI specific timers, start from the end