On Mon, Mar 09, 2015 at 10:09:21AM +0800, Li Jun wrote:
> From: Li Jun <b47...@freescale.com>
> 
> Add a dedicataed normal timer for HNP polling since it's cyclical, while
> in peripheral mode, change a/b_bus_req to be 1 will make it response
> to host request flag with 1, then role switch will be started.

use a_bus_req/b_bus_req

Why hnp polling timer can't use chipidea fsm hrtimer list?

> 
> Signed-off-by: Li Jun <jun...@freescale.com>
> ---
>  drivers/usb/chipidea/ci.h      |    4 ++++
>  drivers/usb/chipidea/otg_fsm.c |   49 
> +++++++++++++++++++++++++++++++++++++---
>  drivers/usb/chipidea/otg_fsm.h |    2 ++
>  3 files changed, 52 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
> index aeec5f0..3192a44 100644
> --- a/drivers/usb/chipidea/ci.h
> +++ b/drivers/usb/chipidea/ci.h
> @@ -166,6 +166,8 @@ struct hw_bank {
>   * @hr_timeouts: time out list for active otg fsm timers
>   * @enabled_otg_timer_bits: bits of enabled otg timers
>   * @next_otg_timer: next nearest enabled timer to be expired
> + * @hnp_polling_timer: cyclical timer for hnp polling
> + * @hnp_polling_req: indicates there is hnp polling request
>   * @work: work for role changing
>   * @wq: workqueue thread
>   * @qh_pool: allocation pool for queue heads
> @@ -212,6 +214,8 @@ struct ci_hdrc {
>       ktime_t                         hr_timeouts[NUM_OTG_FSM_TIMERS];
>       unsigned                        enabled_otg_timer_bits;
>       enum otg_fsm_timer              next_otg_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 083acf4..ed79ae7 100644
> --- a/drivers/usb/chipidea/otg_fsm.c
> +++ b/drivers/usb/chipidea/otg_fsm.c
> @@ -66,6 +66,11 @@ set_a_bus_req(struct device *dev, struct device_attribute 
> *attr,
>                       return count;
>               }
>               ci->fsm.a_bus_req = 1;
> +             if (ci->fsm.otg->state == OTG_STATE_A_PERIPHERAL) {
> +                     ci->gadget.host_request_flag = 1;
> +                     mutex_unlock(&ci->fsm.lock);
> +                     return count;
> +             }
>       }
>  
>       ci_otg_queue_work(ci);
> @@ -144,8 +149,14 @@ set_b_bus_req(struct device *dev, struct 
> device_attribute *attr,
>       mutex_lock(&ci->fsm.lock);
>       if (buf[0] == '0')
>               ci->fsm.b_bus_req = 0;
> -     else if (buf[0] == '1')
> +     else if (buf[0] == '1') {
>               ci->fsm.b_bus_req = 1;
> +             if (ci->fsm.otg->state == OTG_STATE_B_PERIPHERAL) {
> +                     ci->gadget.host_request_flag = 1;
> +                     mutex_unlock(&ci->fsm.lock);
> +                     return count;
> +             }
> +     }
>  
>       ci_otg_queue_work(ci);
>       mutex_unlock(&ci->fsm.lock);
> @@ -203,6 +214,7 @@ static unsigned otg_timer_ms[] = {
>       0,
>       TB_DATA_PLS,
>       TB_SSEND_SRP,
> +     0,
>  };
>  
>  /*
> @@ -358,6 +370,7 @@ static int (*otg_timer_handlers[])(struct ci_hdrc *) = {
>       NULL,                   /* A_WAIT_ENUM */
>       b_data_pls_tmout,       /* B_DATA_PLS */
>       b_ssend_srp_tmout,      /* B_SSEND_SRP */
> +     NULL,                   /* HNP_POLLING */
>  };
>  
>  /*
> @@ -404,15 +417,32 @@ static enum hrtimer_restart ci_otg_hrtimer_func(struct 
> hrtimer *t)
>       return HRTIMER_NORESTART;
>  }
>  
> +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)
>  {
>       hrtimer_init(&ci->otg_fsm_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
>       ci->otg_fsm_hrtimer.function = ci_otg_hrtimer_func;
>  
> +     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 */
>  /* -------------------------------------------------------------*/
> @@ -420,8 +450,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;
>  }
>  
> @@ -569,6 +603,14 @@ int ci_otg_fsm_work(struct ci_hdrc *ci)
>               return 0;
>  
>       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;
> +             }
> +     }
> +

When you do the polling device, it seems you disable the interrupt.

>       if (otg_statemachine(&ci->fsm)) {
>               if (ci->fsm.otg->state == OTG_STATE_A_IDLE) {
>                       /*
> @@ -817,4 +859,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 2689375..fbd6dc7 100644
> --- a/drivers/usb/chipidea/otg_fsm.h
> +++ b/drivers/usb/chipidea/otg_fsm.h
> @@ -62,6 +62,8 @@
>  /* SSEND time before SRP */
>  #define TB_SSEND_SRP         (1500)  /* minimum 1.5 sec, section:5.1.2 */
>  
> +#define T_HOST_REQ_POLL      (1500)  /* HNP polling interval 1s~2s */
> +
>  #ifdef CONFIG_USB_OTG_FSM
>  
>  int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci);
> -- 

-- 

Best Regards,
Peter Chen
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to