Re: [PATCH v3 07/13] usb: chipidea: add OTG fsm operation functions implemenation.

2014-03-12 Thread Li Jun
On Thu, Mar 06, 2014 at 04:13:10PM +0800, Peter Chen wrote:
 On Thu, Mar 06, 2014 at 02:52:17PM +0800, Li Jun wrote:
  On Wed, Mar 05, 2014 at 04:28:14PM +0800, Peter Chen wrote:
   On Thu, Feb 27, 2014 at 07:38:25AM +0800, Li Jun wrote:
Add OTG HNP and SRP operation functions implementation:
- charge vbus
- drive vbus
- connection signaling
- drive sof
- start data pulse
- add fsm timer
- delete fsm timer
- start host
- start gadget

Signed-off-by: Li Jun b47...@freescale.com
---
 drivers/usb/chipidea/bits.h|   11 ++
 drivers/usb/chipidea/ci.h  |1 +
 drivers/usb/chipidea/otg_fsm.c |  231 

 drivers/usb/chipidea/otg_fsm.h |   23 
 4 files changed, 266 insertions(+)

diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
index 83d06c1..c42eb35 100644
--- a/drivers/usb/chipidea/bits.h
+++ b/drivers/usb/chipidea/bits.h
@@ -44,9 +44,14 @@
 #define DEVICEADDR_USBADR (0x7FUL  25)
 
 /* PORTSC */
+#define PORTSC_CCSBIT(0)
+#define PORTSC_CSCBIT(1)
+#define PORTSC_PECBIT(3)
+#define PORTSC_OCCBIT(5)
 #define PORTSC_FPRBIT(6)
 #define PORTSC_SUSP   BIT(7)
 #define PORTSC_HSPBIT(9)
+#define PORTSC_PP BIT(12)
 #define PORTSC_PTC(0x0FUL  16)
 #define PORTSC_PHCD(d)   ((d) ? BIT(22) : BIT(23))
 /* PTS and PTW for non lpm version only */
@@ -56,6 +61,9 @@
 #define PORTSC_PTWBIT(28)
 #define PORTSC_STSBIT(29)
 
+#define PORTSC_W1C_BITS
\
+   (PORTSC_CSC | PORTSC_PEC | PORTSC_OCC)
+
 /* DEVLC */
 #define DEVLC_PFSCBIT(23)
 #define DEVLC_PSPD(0x03UL  25)
@@ -71,7 +79,10 @@
 #define PTS_HSIC  4
 
 /* OTGSC */
+#define OTGSC_VD BIT(0)
+#define OTGSC_VC BIT(1)
 #define OTGSC_IDPU   BIT(5)
+#define OTGSC_HADP   BIT(6)
 #define OTGSC_ID BIT(8)
 #define OTGSC_AVVBIT(9)
 #define OTGSC_ASVBIT(10)
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index db6bf30..171b1d2 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -175,6 +175,7 @@ struct ci_hdrc {
enum ci_rolerole;
boolis_otg;
struct otg_fsm  *fsm;
+   struct ci_otg_fsm_timer_list*fsm_timer;
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 904381e..aa24466 100644
--- a/drivers/usb/chipidea/otg_fsm.c
+++ b/drivers/usb/chipidea/otg_fsm.c
@@ -18,12 +18,242 @@
 #include linux/usb/otg.h
 #include linux/usb/gadget.h
 #include linux/usb/chipidea.h
+#include linux/regulator/consumer.h
 
 #include ci.h
 #include bits.h
 #include otg.h
 #include otg_fsm.h
 
+/* Add timer to active timer list */
+static void ci_otg_add_timer(struct ci_hdrc *ci, enum 
ci_otg_fsm_timer_index t)
+{
+   struct ci_otg_fsm_timer *tmp_timer;
+   struct ci_otg_fsm_timer *timer = ci-fsm_timer-timer_list[t];
+   struct list_head *active_timers = ci-fsm_timer-active_timers;
+
+   if (t = NUM_CI_OTG_FSM_TIMERS)
+   return;
+
+   /*
+* Check if the timer is already in the active list,
+* if so update timer count
+*/
+   list_for_each_entry(tmp_timer, active_timers, list)
+   if (tmp_timer == timer) {
+   timer-count = timer-expires;
+   return;
+   }
+
+   timer-count = timer-expires;
+   list_add_tail(timer-list, active_timers);
+
+   /* Enable 1ms irq */
+   if (!(hw_read(ci, OP_OTGSC, OTGSC_1MSIE)))
+   ci_enable_otg_interrupt(ci, OTGSC_1MSIE);
+}
+
+/* Remove timer from active timer list */
+static void ci_otg_del_timer(struct ci_hdrc *ci, enum 
ci_otg_fsm_timer_index t)
+{
+   struct ci_otg_fsm_timer *tmp_timer, *del_tmp;
+   struct ci_otg_fsm_timer *timer = ci-fsm_timer-timer_list[t];
+   struct list_head *active_timers = ci-fsm_timer-active_timers;
+   int flag = 0;
+
+   if (t = NUM_CI_OTG_FSM_TIMERS)
+   return;
+
+   list_for_each_entry_safe(tmp_timer, del_tmp, active_timers, 
list)
+   if (tmp_timer == timer) {
+   list_del(timer-list);

RE: [PATCH v3 07/13] usb: chipidea: add OTG fsm operation functions implemenation.

2014-03-12 Thread Peter Chen
 
   Yes, gadget is not linked to OTG fsm, I did not find a better way to
   get ci here, actually this patchset is adding a otg_fsm *pointer*
   instead of struct otg_fsm into struct ci_hdrc, directly embed
   otg_fsm is a big cost since it's also a some big structure.
 
  I think keep the code easy to read and maintain are important just
  waste tens of bytes for some controllers. I prefer to use struct than
  pointer for otg_fsm at struct ci_hdrc.
 
 
 OK, I will directly embed it.
 
  I checked struct otg_fsm, lots of entries are defined with int, in
  fact, it doesn't necessary, defined as unsigned xxx:1 is enough.
 
 
 That's true, I will create a separated patch for it.
 

But it needs to change otg_timer_initializer, it can't get bit address.

Peter
--
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


Re: [PATCH v3 07/13] usb: chipidea: add OTG fsm operation functions implemenation.

2014-03-06 Thread Peter Chen
On Thu, Mar 06, 2014 at 02:52:17PM +0800, Li Jun wrote:
 On Wed, Mar 05, 2014 at 04:28:14PM +0800, Peter Chen wrote:
  On Thu, Feb 27, 2014 at 07:38:25AM +0800, Li Jun wrote:
   Add OTG HNP and SRP operation functions implementation:
   - charge vbus
   - drive vbus
   - connection signaling
   - drive sof
   - start data pulse
   - add fsm timer
   - delete fsm timer
   - start host
   - start gadget
   
   Signed-off-by: Li Jun b47...@freescale.com
   ---
drivers/usb/chipidea/bits.h|   11 ++
drivers/usb/chipidea/ci.h  |1 +
drivers/usb/chipidea/otg_fsm.c |  231 
   
drivers/usb/chipidea/otg_fsm.h |   23 
4 files changed, 266 insertions(+)
   
   diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
   index 83d06c1..c42eb35 100644
   --- a/drivers/usb/chipidea/bits.h
   +++ b/drivers/usb/chipidea/bits.h
   @@ -44,9 +44,14 @@
#define DEVICEADDR_USBADR (0x7FUL  25)

/* PORTSC */
   +#define PORTSC_CCSBIT(0)
   +#define PORTSC_CSCBIT(1)
   +#define PORTSC_PECBIT(3)
   +#define PORTSC_OCCBIT(5)
#define PORTSC_FPRBIT(6)
#define PORTSC_SUSP   BIT(7)
#define PORTSC_HSPBIT(9)
   +#define PORTSC_PP BIT(12)
#define PORTSC_PTC(0x0FUL  16)
#define PORTSC_PHCD(d) ((d) ? BIT(22) : BIT(23))
/* PTS and PTW for non lpm version only */
   @@ -56,6 +61,9 @@
#define PORTSC_PTWBIT(28)
#define PORTSC_STSBIT(29)

   +#define PORTSC_W1C_BITS  \
   + (PORTSC_CSC | PORTSC_PEC | PORTSC_OCC)
   +
/* DEVLC */
#define DEVLC_PFSCBIT(23)
#define DEVLC_PSPD(0x03UL  25)
   @@ -71,7 +79,10 @@
#define PTS_HSIC  4

/* OTGSC */
   +#define OTGSC_VD   BIT(0)
   +#define OTGSC_VC   BIT(1)
#define OTGSC_IDPU BIT(5)
   +#define OTGSC_HADP BIT(6)
#define OTGSC_ID   BIT(8)
#define OTGSC_AVV  BIT(9)
#define OTGSC_ASV  BIT(10)
   diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
   index db6bf30..171b1d2 100644
   --- a/drivers/usb/chipidea/ci.h
   +++ b/drivers/usb/chipidea/ci.h
   @@ -175,6 +175,7 @@ struct ci_hdrc {
 enum ci_rolerole;
 boolis_otg;
 struct otg_fsm  *fsm;
   + struct ci_otg_fsm_timer_list*fsm_timer;
 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 904381e..aa24466 100644
   --- a/drivers/usb/chipidea/otg_fsm.c
   +++ b/drivers/usb/chipidea/otg_fsm.c
   @@ -18,12 +18,242 @@
#include linux/usb/otg.h
#include linux/usb/gadget.h
#include linux/usb/chipidea.h
   +#include linux/regulator/consumer.h

#include ci.h
#include bits.h
#include otg.h
#include otg_fsm.h

   +/* Add timer to active timer list */
   +static void ci_otg_add_timer(struct ci_hdrc *ci, enum 
   ci_otg_fsm_timer_index t)
   +{
   + struct ci_otg_fsm_timer *tmp_timer;
   + struct ci_otg_fsm_timer *timer = ci-fsm_timer-timer_list[t];
   + struct list_head *active_timers = ci-fsm_timer-active_timers;
   +
   + if (t = NUM_CI_OTG_FSM_TIMERS)
   + return;
   +
   + /*
   +  * Check if the timer is already in the active list,
   +  * if so update timer count
   +  */
   + list_for_each_entry(tmp_timer, active_timers, list)
   + if (tmp_timer == timer) {
   + timer-count = timer-expires;
   + return;
   + }
   +
   + timer-count = timer-expires;
   + list_add_tail(timer-list, active_timers);
   +
   + /* Enable 1ms irq */
   + if (!(hw_read(ci, OP_OTGSC, OTGSC_1MSIE)))
   + ci_enable_otg_interrupt(ci, OTGSC_1MSIE);
   +}
   +
   +/* Remove timer from active timer list */
   +static void ci_otg_del_timer(struct ci_hdrc *ci, enum 
   ci_otg_fsm_timer_index t)
   +{
   + struct ci_otg_fsm_timer *tmp_timer, *del_tmp;
   + struct ci_otg_fsm_timer *timer = ci-fsm_timer-timer_list[t];
   + struct list_head *active_timers = ci-fsm_timer-active_timers;
   + int flag = 0;
   +
   + if (t = NUM_CI_OTG_FSM_TIMERS)
   + return;
   +
   + list_for_each_entry_safe(tmp_timer, del_tmp, active_timers, list)
   + if (tmp_timer == timer) {
   + list_del(timer-list);
   + flag = 1;
   + }
   +
   + /* Disable 1ms irq if there is no any active timer */
   + if ((flag == 1)  list_empty(active_timers))
   + ci_disable_otg_interrupt(ci, OTGSC_1MSIE);
   +}
  
  Why variable flag is needed?
  
 
 with this flag check, driver need not do irq disable again when the timer
 was already deleted.
 

It only needs to disable 1ms timer interrupt when there is no active 

Re: [PATCH v3 07/13] usb: chipidea: add OTG fsm operation functions implemenation.

2014-03-05 Thread Peter Chen
On Thu, Feb 27, 2014 at 07:38:25AM +0800, Li Jun wrote:
 Add OTG HNP and SRP operation functions implementation:
 - charge vbus
 - drive vbus
 - connection signaling
 - drive sof
 - start data pulse
 - add fsm timer
 - delete fsm timer
 - start host
 - start gadget
 
 Signed-off-by: Li Jun b47...@freescale.com
 ---
  drivers/usb/chipidea/bits.h|   11 ++
  drivers/usb/chipidea/ci.h  |1 +
  drivers/usb/chipidea/otg_fsm.c |  231 
 
  drivers/usb/chipidea/otg_fsm.h |   23 
  4 files changed, 266 insertions(+)
 
 diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
 index 83d06c1..c42eb35 100644
 --- a/drivers/usb/chipidea/bits.h
 +++ b/drivers/usb/chipidea/bits.h
 @@ -44,9 +44,14 @@
  #define DEVICEADDR_USBADR (0x7FUL  25)
  
  /* PORTSC */
 +#define PORTSC_CCSBIT(0)
 +#define PORTSC_CSCBIT(1)
 +#define PORTSC_PECBIT(3)
 +#define PORTSC_OCCBIT(5)
  #define PORTSC_FPRBIT(6)
  #define PORTSC_SUSP   BIT(7)
  #define PORTSC_HSPBIT(9)
 +#define PORTSC_PP BIT(12)
  #define PORTSC_PTC(0x0FUL  16)
  #define PORTSC_PHCD(d) ((d) ? BIT(22) : BIT(23))
  /* PTS and PTW for non lpm version only */
 @@ -56,6 +61,9 @@
  #define PORTSC_PTWBIT(28)
  #define PORTSC_STSBIT(29)
  
 +#define PORTSC_W1C_BITS  \
 + (PORTSC_CSC | PORTSC_PEC | PORTSC_OCC)
 +
  /* DEVLC */
  #define DEVLC_PFSCBIT(23)
  #define DEVLC_PSPD(0x03UL  25)
 @@ -71,7 +79,10 @@
  #define PTS_HSIC  4
  
  /* OTGSC */
 +#define OTGSC_VD   BIT(0)
 +#define OTGSC_VC   BIT(1)
  #define OTGSC_IDPU BIT(5)
 +#define OTGSC_HADP BIT(6)
  #define OTGSC_ID   BIT(8)
  #define OTGSC_AVV  BIT(9)
  #define OTGSC_ASV  BIT(10)
 diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
 index db6bf30..171b1d2 100644
 --- a/drivers/usb/chipidea/ci.h
 +++ b/drivers/usb/chipidea/ci.h
 @@ -175,6 +175,7 @@ struct ci_hdrc {
   enum ci_rolerole;
   boolis_otg;
   struct otg_fsm  *fsm;
 + struct ci_otg_fsm_timer_list*fsm_timer;
   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 904381e..aa24466 100644
 --- a/drivers/usb/chipidea/otg_fsm.c
 +++ b/drivers/usb/chipidea/otg_fsm.c
 @@ -18,12 +18,242 @@
  #include linux/usb/otg.h
  #include linux/usb/gadget.h
  #include linux/usb/chipidea.h
 +#include linux/regulator/consumer.h
  
  #include ci.h
  #include bits.h
  #include otg.h
  #include otg_fsm.h
  
 +/* Add timer to active timer list */
 +static void ci_otg_add_timer(struct ci_hdrc *ci, enum ci_otg_fsm_timer_index 
 t)
 +{
 + struct ci_otg_fsm_timer *tmp_timer;
 + struct ci_otg_fsm_timer *timer = ci-fsm_timer-timer_list[t];
 + struct list_head *active_timers = ci-fsm_timer-active_timers;
 +
 + if (t = NUM_CI_OTG_FSM_TIMERS)
 + return;
 +
 + /*
 +  * Check if the timer is already in the active list,
 +  * if so update timer count
 +  */
 + list_for_each_entry(tmp_timer, active_timers, list)
 + if (tmp_timer == timer) {
 + timer-count = timer-expires;
 + return;
 + }
 +
 + timer-count = timer-expires;
 + list_add_tail(timer-list, active_timers);
 +
 + /* Enable 1ms irq */
 + if (!(hw_read(ci, OP_OTGSC, OTGSC_1MSIE)))
 + ci_enable_otg_interrupt(ci, OTGSC_1MSIE);
 +}
 +
 +/* Remove timer from active timer list */
 +static void ci_otg_del_timer(struct ci_hdrc *ci, enum ci_otg_fsm_timer_index 
 t)
 +{
 + struct ci_otg_fsm_timer *tmp_timer, *del_tmp;
 + struct ci_otg_fsm_timer *timer = ci-fsm_timer-timer_list[t];
 + struct list_head *active_timers = ci-fsm_timer-active_timers;
 + int flag = 0;
 +
 + if (t = NUM_CI_OTG_FSM_TIMERS)
 + return;
 +
 + list_for_each_entry_safe(tmp_timer, del_tmp, active_timers, list)
 + if (tmp_timer == timer) {
 + list_del(timer-list);
 + flag = 1;
 + }
 +
 + /* Disable 1ms irq if there is no any active timer */
 + if ((flag == 1)  list_empty(active_timers))
 + ci_disable_otg_interrupt(ci, OTGSC_1MSIE);
 +}

Why variable flag is needed?

 +
 +/* -*/
 +/* Operations that will be called from OTG Finite State Machine */
 +/* -*/
 +static void ci_otg_fsm_add_timer(struct otg_fsm *fsm, enum otg_fsm_timer t)
 +{
 + struct ci_hdrc  *ci = container_of(fsm-otg-gadget,
 + struct ci_hdrc, gadget);


Re: [PATCH v3 07/13] usb: chipidea: add OTG fsm operation functions implemenation.

2014-03-05 Thread Li Jun
On Wed, Mar 05, 2014 at 04:28:14PM +0800, Peter Chen wrote:
 On Thu, Feb 27, 2014 at 07:38:25AM +0800, Li Jun wrote:
  Add OTG HNP and SRP operation functions implementation:
  - charge vbus
  - drive vbus
  - connection signaling
  - drive sof
  - start data pulse
  - add fsm timer
  - delete fsm timer
  - start host
  - start gadget
  
  Signed-off-by: Li Jun b47...@freescale.com
  ---
   drivers/usb/chipidea/bits.h|   11 ++
   drivers/usb/chipidea/ci.h  |1 +
   drivers/usb/chipidea/otg_fsm.c |  231 
  
   drivers/usb/chipidea/otg_fsm.h |   23 
   4 files changed, 266 insertions(+)
  
  diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
  index 83d06c1..c42eb35 100644
  --- a/drivers/usb/chipidea/bits.h
  +++ b/drivers/usb/chipidea/bits.h
  @@ -44,9 +44,14 @@
   #define DEVICEADDR_USBADR (0x7FUL  25)
   
   /* PORTSC */
  +#define PORTSC_CCSBIT(0)
  +#define PORTSC_CSCBIT(1)
  +#define PORTSC_PECBIT(3)
  +#define PORTSC_OCCBIT(5)
   #define PORTSC_FPRBIT(6)
   #define PORTSC_SUSP   BIT(7)
   #define PORTSC_HSPBIT(9)
  +#define PORTSC_PP BIT(12)
   #define PORTSC_PTC(0x0FUL  16)
   #define PORTSC_PHCD(d)   ((d) ? BIT(22) : BIT(23))
   /* PTS and PTW for non lpm version only */
  @@ -56,6 +61,9 @@
   #define PORTSC_PTWBIT(28)
   #define PORTSC_STSBIT(29)
   
  +#define PORTSC_W1C_BITS\
  +   (PORTSC_CSC | PORTSC_PEC | PORTSC_OCC)
  +
   /* DEVLC */
   #define DEVLC_PFSCBIT(23)
   #define DEVLC_PSPD(0x03UL  25)
  @@ -71,7 +79,10 @@
   #define PTS_HSIC  4
   
   /* OTGSC */
  +#define OTGSC_VD BIT(0)
  +#define OTGSC_VC BIT(1)
   #define OTGSC_IDPU   BIT(5)
  +#define OTGSC_HADP   BIT(6)
   #define OTGSC_ID BIT(8)
   #define OTGSC_AVVBIT(9)
   #define OTGSC_ASVBIT(10)
  diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
  index db6bf30..171b1d2 100644
  --- a/drivers/usb/chipidea/ci.h
  +++ b/drivers/usb/chipidea/ci.h
  @@ -175,6 +175,7 @@ struct ci_hdrc {
  enum ci_rolerole;
  boolis_otg;
  struct otg_fsm  *fsm;
  +   struct ci_otg_fsm_timer_list*fsm_timer;
  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 904381e..aa24466 100644
  --- a/drivers/usb/chipidea/otg_fsm.c
  +++ b/drivers/usb/chipidea/otg_fsm.c
  @@ -18,12 +18,242 @@
   #include linux/usb/otg.h
   #include linux/usb/gadget.h
   #include linux/usb/chipidea.h
  +#include linux/regulator/consumer.h
   
   #include ci.h
   #include bits.h
   #include otg.h
   #include otg_fsm.h
   
  +/* Add timer to active timer list */
  +static void ci_otg_add_timer(struct ci_hdrc *ci, enum 
  ci_otg_fsm_timer_index t)
  +{
  +   struct ci_otg_fsm_timer *tmp_timer;
  +   struct ci_otg_fsm_timer *timer = ci-fsm_timer-timer_list[t];
  +   struct list_head *active_timers = ci-fsm_timer-active_timers;
  +
  +   if (t = NUM_CI_OTG_FSM_TIMERS)
  +   return;
  +
  +   /*
  +* Check if the timer is already in the active list,
  +* if so update timer count
  +*/
  +   list_for_each_entry(tmp_timer, active_timers, list)
  +   if (tmp_timer == timer) {
  +   timer-count = timer-expires;
  +   return;
  +   }
  +
  +   timer-count = timer-expires;
  +   list_add_tail(timer-list, active_timers);
  +
  +   /* Enable 1ms irq */
  +   if (!(hw_read(ci, OP_OTGSC, OTGSC_1MSIE)))
  +   ci_enable_otg_interrupt(ci, OTGSC_1MSIE);
  +}
  +
  +/* Remove timer from active timer list */
  +static void ci_otg_del_timer(struct ci_hdrc *ci, enum 
  ci_otg_fsm_timer_index t)
  +{
  +   struct ci_otg_fsm_timer *tmp_timer, *del_tmp;
  +   struct ci_otg_fsm_timer *timer = ci-fsm_timer-timer_list[t];
  +   struct list_head *active_timers = ci-fsm_timer-active_timers;
  +   int flag = 0;
  +
  +   if (t = NUM_CI_OTG_FSM_TIMERS)
  +   return;
  +
  +   list_for_each_entry_safe(tmp_timer, del_tmp, active_timers, list)
  +   if (tmp_timer == timer) {
  +   list_del(timer-list);
  +   flag = 1;
  +   }
  +
  +   /* Disable 1ms irq if there is no any active timer */
  +   if ((flag == 1)  list_empty(active_timers))
  +   ci_disable_otg_interrupt(ci, OTGSC_1MSIE);
  +}
 
 Why variable flag is needed?
 

with this flag check, driver need not do irq disable again when the timer
was already deleted.

Li Jun
  +
  +/* -*/
  +/* Operations that will be called from OTG Finite State Machine */
  +/* 

[PATCH v3 07/13] usb: chipidea: add OTG fsm operation functions implemenation.

2014-02-26 Thread Li Jun
Add OTG HNP and SRP operation functions implementation:
- charge vbus
- drive vbus
- connection signaling
- drive sof
- start data pulse
- add fsm timer
- delete fsm timer
- start host
- start gadget

Signed-off-by: Li Jun b47...@freescale.com
---
 drivers/usb/chipidea/bits.h|   11 ++
 drivers/usb/chipidea/ci.h  |1 +
 drivers/usb/chipidea/otg_fsm.c |  231 
 drivers/usb/chipidea/otg_fsm.h |   23 
 4 files changed, 266 insertions(+)

diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
index 83d06c1..c42eb35 100644
--- a/drivers/usb/chipidea/bits.h
+++ b/drivers/usb/chipidea/bits.h
@@ -44,9 +44,14 @@
 #define DEVICEADDR_USBADR (0x7FUL  25)
 
 /* PORTSC */
+#define PORTSC_CCSBIT(0)
+#define PORTSC_CSCBIT(1)
+#define PORTSC_PECBIT(3)
+#define PORTSC_OCCBIT(5)
 #define PORTSC_FPRBIT(6)
 #define PORTSC_SUSP   BIT(7)
 #define PORTSC_HSPBIT(9)
+#define PORTSC_PP BIT(12)
 #define PORTSC_PTC(0x0FUL  16)
 #define PORTSC_PHCD(d)   ((d) ? BIT(22) : BIT(23))
 /* PTS and PTW for non lpm version only */
@@ -56,6 +61,9 @@
 #define PORTSC_PTWBIT(28)
 #define PORTSC_STSBIT(29)
 
+#define PORTSC_W1C_BITS\
+   (PORTSC_CSC | PORTSC_PEC | PORTSC_OCC)
+
 /* DEVLC */
 #define DEVLC_PFSCBIT(23)
 #define DEVLC_PSPD(0x03UL  25)
@@ -71,7 +79,10 @@
 #define PTS_HSIC  4
 
 /* OTGSC */
+#define OTGSC_VD BIT(0)
+#define OTGSC_VC BIT(1)
 #define OTGSC_IDPU   BIT(5)
+#define OTGSC_HADP   BIT(6)
 #define OTGSC_ID BIT(8)
 #define OTGSC_AVVBIT(9)
 #define OTGSC_ASVBIT(10)
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index db6bf30..171b1d2 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -175,6 +175,7 @@ struct ci_hdrc {
enum ci_rolerole;
boolis_otg;
struct otg_fsm  *fsm;
+   struct ci_otg_fsm_timer_list*fsm_timer;
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 904381e..aa24466 100644
--- a/drivers/usb/chipidea/otg_fsm.c
+++ b/drivers/usb/chipidea/otg_fsm.c
@@ -18,12 +18,242 @@
 #include linux/usb/otg.h
 #include linux/usb/gadget.h
 #include linux/usb/chipidea.h
+#include linux/regulator/consumer.h
 
 #include ci.h
 #include bits.h
 #include otg.h
 #include otg_fsm.h
 
+/* Add timer to active timer list */
+static void ci_otg_add_timer(struct ci_hdrc *ci, enum ci_otg_fsm_timer_index t)
+{
+   struct ci_otg_fsm_timer *tmp_timer;
+   struct ci_otg_fsm_timer *timer = ci-fsm_timer-timer_list[t];
+   struct list_head *active_timers = ci-fsm_timer-active_timers;
+
+   if (t = NUM_CI_OTG_FSM_TIMERS)
+   return;
+
+   /*
+* Check if the timer is already in the active list,
+* if so update timer count
+*/
+   list_for_each_entry(tmp_timer, active_timers, list)
+   if (tmp_timer == timer) {
+   timer-count = timer-expires;
+   return;
+   }
+
+   timer-count = timer-expires;
+   list_add_tail(timer-list, active_timers);
+
+   /* Enable 1ms irq */
+   if (!(hw_read(ci, OP_OTGSC, OTGSC_1MSIE)))
+   ci_enable_otg_interrupt(ci, OTGSC_1MSIE);
+}
+
+/* Remove timer from active timer list */
+static void ci_otg_del_timer(struct ci_hdrc *ci, enum ci_otg_fsm_timer_index t)
+{
+   struct ci_otg_fsm_timer *tmp_timer, *del_tmp;
+   struct ci_otg_fsm_timer *timer = ci-fsm_timer-timer_list[t];
+   struct list_head *active_timers = ci-fsm_timer-active_timers;
+   int flag = 0;
+
+   if (t = NUM_CI_OTG_FSM_TIMERS)
+   return;
+
+   list_for_each_entry_safe(tmp_timer, del_tmp, active_timers, list)
+   if (tmp_timer == timer) {
+   list_del(timer-list);
+   flag = 1;
+   }
+
+   /* Disable 1ms irq if there is no any active timer */
+   if ((flag == 1)  list_empty(active_timers))
+   ci_disable_otg_interrupt(ci, OTGSC_1MSIE);
+}
+
+/* -*/
+/* Operations that will be called from OTG Finite State Machine */
+/* -*/
+static void ci_otg_fsm_add_timer(struct otg_fsm *fsm, enum otg_fsm_timer t)
+{
+   struct ci_hdrc  *ci = container_of(fsm-otg-gadget,
+   struct ci_hdrc, gadget);
+
+   if (t  NUM_OTG_FSM_TIMERS)
+   ci_otg_add_timer(ci, t);
+   return;
+}
+
+static void ci_otg_fsm_del_timer(struct