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;
}
Beispiel #2
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);
}
Beispiel #3
0
/**
 * 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;
}
Beispiel #4
0
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);
	}
}