static int ci_is_vbus_glitch(struct ci_hdrc *ci) { int i; for (i = 0; i < CI_VBUS_CONNECT_TIMEOUT_MS/20; i++) { if (hw_read_otgsc(ci, OTGSC_AVV)) { return 0; } else if (!hw_read_otgsc(ci, OTGSC_BSV)) { dev_warn(ci->dev, "there is a vbus glitch\n"); return 1; } msleep(20); } return 0; }
/* * 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_otgsc(ci, OTGSC_1MSIE))) hw_write_otgsc(ci, OTGSC_1MSIE, OTGSC_1MSIE); }
/** * ci_otg_role - pick role based on ID pin state * @ci: the controller */ enum ci_role ci_otg_role(struct ci_hdrc *ci) { enum ci_role role = hw_read_otgsc(ci, OTGSC_ID) ? CI_ROLE_GADGET : CI_ROLE_HOST; return role; }
void ci_handle_vbus_change(struct ci_hdrc *ci) { if (!ci->is_otg) return; if (hw_read_otgsc(ci, OTGSC_BSV)) usb_gadget_vbus_connect(&ci->gadget); else usb_gadget_vbus_disconnect(&ci->gadget); }
void ci_handle_vbus_connected(struct ci_hdrc *ci) { /* * TODO: if the platform does not supply 5v to udc, or use other way * to supply 5v, it needs to use other conditions to call * usb_gadget_vbus_connect. */ if (!ci->is_otg) return; if (hw_read_otgsc(ci, OTGSC_BSV) && !ci_is_vbus_glitch(ci)) usb_gadget_vbus_connect(&ci->gadget); }
static void ci_handle_vbus_glitch(struct ci_hdrc *ci) { bool valid_vbus_change = false; if (hw_read_otgsc(ci, OTGSC_BSV)) { if (!ci_is_vbus_glitch(ci)) { if (ci_otg_is_fsm_mode(ci)) { ci->fsm.b_sess_vld = 1; ci->fsm.b_ssend_srp = 0; otg_del_timer(&ci->fsm, B_SSEND_SRP); otg_del_timer(&ci->fsm, B_SRP_FAIL); } valid_vbus_change = true; } } else { if (ci->vbus_active && !ci_otg_is_fsm_mode(ci)) valid_vbus_change = true; } if (valid_vbus_change) { ci->b_sess_valid_event = true; ci_otg_queue_work(ci); } }