Re: [PATCH v3 07/13] usb: chipidea: add OTG fsm operation functions implemenation.
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.
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.
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.
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.
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.
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