Enscript Output

extractedLnx/linux-2.6.38/drivers/usb/otg/langwell_otg.c_langwell_otg_work.c

static void langwell_otg_work(struct work_struct *work)
{
	struct langwell_otg		*lnw;
	struct intel_mid_otg_xceiv	*iotg;
	int				retval;
	struct pci_dev			*pdev;

	lnw = container_of(work, struct langwell_otg, work);
	iotg = &lnw->iotg;
	pdev = to_pci_dev(lnw->dev);

	dev_dbg(lnw->dev, "%s: old state = %s\n", __func__,
			state_string(iotg->otg.state));

	switch (iotg->otg.state) {
	case OTG_STATE_UNDEFINED:
	case OTG_STATE_B_IDLE:
		if (!iotg->hsm.id) {
			langwell_otg_del_timer(b_srp_init_tmr);
			del_timer_sync(&lnw->hsm_timer);

			iotg->otg.default_a = 1;
			iotg->hsm.a_srp_det = 0;

			langwell_otg_chrg_vbus(0);
			set_host_mode();
			langwell_otg_phy_low_power(1);

			iotg->otg.state = OTG_STATE_A_IDLE;
			langwell_update_transceiver();
		} else if (iotg->hsm.b_sess_vld) {
			langwell_otg_del_timer(b_srp_init_tmr);
			del_timer_sync(&lnw->hsm_timer);
			iotg->hsm.b_sess_end = 0;
			iotg->hsm.a_bus_suspend = 0;
			langwell_otg_chrg_vbus(0);

			if (lnw->iotg.start_peripheral) {
				lnw->iotg.start_peripheral(&lnw->iotg);
				iotg->otg.state = OTG_STATE_B_PERIPHERAL;
			} else
				dev_dbg(lnw->dev, "client driver not loaded\n");

		} else if (iotg->hsm.b_srp_init_tmout) {
			iotg->hsm.b_srp_init_tmout = 0;
			dev_warn(lnw->dev, "SRP init timeout\n");
		} else if (iotg->hsm.b_srp_fail_tmout) {
			iotg->hsm.b_srp_fail_tmout = 0;
			iotg->hsm.b_bus_req = 0;

			/* No silence failure */
			langwell_otg_nsf_msg(6);
		} else if (iotg->hsm.b_bus_req && iotg->hsm.b_sess_end) {
			del_timer_sync(&lnw->hsm_timer);
			/* workaround for b_se0_srp detection */
			retval = langwell_otg_check_se0_srp(0);
			if (retval) {
				iotg->hsm.b_bus_req = 0;
				dev_dbg(lnw->dev, "LS isn't SE0, try later\n");
			} else {
				/* clear the PHCD before start srp */
				langwell_otg_phy_low_power(0);

				/* Start SRP */
				langwell_otg_add_timer(b_srp_init_tmr);
				iotg->otg.start_srp(&iotg->otg);
				langwell_otg_del_timer(b_srp_init_tmr);
				langwell_otg_add_ktimer(TB_SRP_FAIL_TMR);

				/* reset PHY low power mode here */
				langwell_otg_phy_low_power_wait(1);
			}
		}
		break;
	case OTG_STATE_B_SRP_INIT:
		if (!iotg->hsm.id) {
			iotg->otg.default_a = 1;
			iotg->hsm.a_srp_det = 0;

			/* Turn off VBus */
			iotg->otg.set_vbus(&iotg->otg, false);
			langwell_otg_chrg_vbus(0);
			set_host_mode();
			langwell_otg_phy_low_power(1);
			iotg->otg.state = OTG_STATE_A_IDLE;
			langwell_update_transceiver();
		} else if (iotg->hsm.b_sess_vld) {
			langwell_otg_chrg_vbus(0);
			if (lnw->iotg.start_peripheral) {
				lnw->iotg.start_peripheral(&lnw->iotg);
				iotg->otg.state = OTG_STATE_B_PERIPHERAL;
			} else
				dev_dbg(lnw->dev, "client driver not loaded\n");
		}
		break;
	case OTG_STATE_B_PERIPHERAL:
		if (!iotg->hsm.id) {
			iotg->otg.default_a = 1;
			iotg->hsm.a_srp_det = 0;

			langwell_otg_chrg_vbus(0);

			if (lnw->iotg.stop_peripheral)
				lnw->iotg.stop_peripheral(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"client driver has been removed.\n");

			set_host_mode();
			langwell_otg_phy_low_power(1);
			iotg->otg.state = OTG_STATE_A_IDLE;
			langwell_update_transceiver();
		} else if (!iotg->hsm.b_sess_vld) {
			iotg->hsm.b_hnp_enable = 0;

			if (lnw->iotg.stop_peripheral)
				lnw->iotg.stop_peripheral(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"client driver has been removed.\n");

			iotg->otg.state = OTG_STATE_B_IDLE;
		} else if (iotg->hsm.b_bus_req && iotg->otg.gadget &&
					iotg->otg.gadget->b_hnp_enable &&
					iotg->hsm.a_bus_suspend) {

			if (lnw->iotg.stop_peripheral)
				lnw->iotg.stop_peripheral(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"client driver has been removed.\n");

			langwell_otg_HAAR(1);
			iotg->hsm.a_conn = 0;

			if (lnw->iotg.start_host) {
				lnw->iotg.start_host(&lnw->iotg);
				iotg->otg.state = OTG_STATE_B_WAIT_ACON;
			} else
				dev_dbg(lnw->dev,
						"host driver not loaded.\n");

			iotg->hsm.a_bus_resume = 0;
			langwell_otg_add_ktimer(TB_ASE0_BRST_TMR);
		}
		break;

	case OTG_STATE_B_WAIT_ACON:
		if (!iotg->hsm.id) {
			/* delete hsm timer for b_ase0_brst_tmr */
			del_timer_sync(&lnw->hsm_timer);

			iotg->otg.default_a = 1;
			iotg->hsm.a_srp_det = 0;

			langwell_otg_chrg_vbus(0);

			langwell_otg_HAAR(0);
			if (lnw->iotg.stop_host)
				lnw->iotg.stop_host(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"host driver has been removed.\n");

			set_host_mode();
			langwell_otg_phy_low_power(1);
			iotg->otg.state = OTG_STATE_A_IDLE;
			langwell_update_transceiver();
		} else if (!iotg->hsm.b_sess_vld) {
			/* delete hsm timer for b_ase0_brst_tmr */
			del_timer_sync(&lnw->hsm_timer);

			iotg->hsm.b_hnp_enable = 0;
			iotg->hsm.b_bus_req = 0;

			langwell_otg_chrg_vbus(0);
			langwell_otg_HAAR(0);

			if (lnw->iotg.stop_host)
				lnw->iotg.stop_host(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"host driver has been removed.\n");

			set_client_mode();
			langwell_otg_phy_low_power(1);
			iotg->otg.state = OTG_STATE_B_IDLE;
		} else if (iotg->hsm.a_conn) {
			/* delete hsm timer for b_ase0_brst_tmr */
			del_timer_sync(&lnw->hsm_timer);

			langwell_otg_HAAR(0);
			iotg->otg.state = OTG_STATE_B_HOST;
			langwell_update_transceiver();
		} else if (iotg->hsm.a_bus_resume ||
				iotg->hsm.b_ase0_brst_tmout) {
			/* delete hsm timer for b_ase0_brst_tmr */
			del_timer_sync(&lnw->hsm_timer);

			langwell_otg_HAAR(0);
			langwell_otg_nsf_msg(7);

			if (lnw->iotg.stop_host)
				lnw->iotg.stop_host(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"host driver has been removed.\n");

			iotg->hsm.a_bus_suspend = 0;
			iotg->hsm.b_bus_req = 0;

			if (lnw->iotg.start_peripheral)
				lnw->iotg.start_peripheral(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"client driver not loaded.\n");

			iotg->otg.state = OTG_STATE_B_PERIPHERAL;
		}
		break;

	case OTG_STATE_B_HOST:
		if (!iotg->hsm.id) {
			iotg->otg.default_a = 1;
			iotg->hsm.a_srp_det = 0;

			langwell_otg_chrg_vbus(0);

			if (lnw->iotg.stop_host)
				lnw->iotg.stop_host(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"host driver has been removed.\n");

			set_host_mode();
			langwell_otg_phy_low_power(1);
			iotg->otg.state = OTG_STATE_A_IDLE;
			langwell_update_transceiver();
		} else if (!iotg->hsm.b_sess_vld) {
			iotg->hsm.b_hnp_enable = 0;
			iotg->hsm.b_bus_req = 0;

			langwell_otg_chrg_vbus(0);
			if (lnw->iotg.stop_host)
				lnw->iotg.stop_host(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"host driver has been removed.\n");

			set_client_mode();
			langwell_otg_phy_low_power(1);
			iotg->otg.state = OTG_STATE_B_IDLE;
		} else if ((!iotg->hsm.b_bus_req) ||
				(!iotg->hsm.a_conn)) {
			iotg->hsm.b_bus_req = 0;
			langwell_otg_loc_sof(0);

			if (lnw->iotg.stop_host)
				lnw->iotg.stop_host(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"host driver has been removed.\n");

			iotg->hsm.a_bus_suspend = 0;

			if (lnw->iotg.start_peripheral)
				lnw->iotg.start_peripheral(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
						"client driver not loaded.\n");

			iotg->otg.state = OTG_STATE_B_PERIPHERAL;
		}
		break;

	case OTG_STATE_A_IDLE:
		iotg->otg.default_a = 1;
		if (iotg->hsm.id) {
			iotg->otg.default_a = 0;
			iotg->hsm.b_bus_req = 0;
			iotg->hsm.vbus_srp_up = 0;

			langwell_otg_chrg_vbus(0);
			set_client_mode();
			langwell_otg_phy_low_power(1);
			iotg->otg.state = OTG_STATE_B_IDLE;
			langwell_update_transceiver();
		} else if (!iotg->hsm.a_bus_drop &&
			(iotg->hsm.a_srp_det || iotg->hsm.a_bus_req)) {
			langwell_otg_phy_low_power(0);

			/* Turn on VBus */
			iotg->otg.set_vbus(&iotg->otg, true);

			iotg->hsm.vbus_srp_up = 0;
			iotg->hsm.a_wait_vrise_tmout = 0;
			langwell_otg_add_timer(a_wait_vrise_tmr);
			iotg->otg.state = OTG_STATE_A_WAIT_VRISE;
			langwell_update_transceiver();
		} else if (!iotg->hsm.a_bus_drop && iotg->hsm.a_sess_vld) {
			iotg->hsm.vbus_srp_up = 1;
		} else if (!iotg->hsm.a_sess_vld && iotg->hsm.vbus_srp_up) {
			msleep(10);
			langwell_otg_phy_low_power(0);

			/* Turn on VBus */
			iotg->otg.set_vbus(&iotg->otg, true);
			iotg->hsm.a_srp_det = 1;
			iotg->hsm.vbus_srp_up = 0;
			iotg->hsm.a_wait_vrise_tmout = 0;
			langwell_otg_add_timer(a_wait_vrise_tmr);
			iotg->otg.state = OTG_STATE_A_WAIT_VRISE;
			langwell_update_transceiver();
		} else if (!iotg->hsm.a_sess_vld &&
				!iotg->hsm.vbus_srp_up) {
			langwell_otg_phy_low_power(1);
		}
		break;
	case OTG_STATE_A_WAIT_VRISE:
		if (iotg->hsm.id) {
			langwell_otg_del_timer(a_wait_vrise_tmr);
			iotg->hsm.b_bus_req = 0;
			iotg->otg.default_a = 0;

			/* Turn off VBus */
			iotg->otg.set_vbus(&iotg->otg, false);
			set_client_mode();
			langwell_otg_phy_low_power_wait(1);
			iotg->otg.state = OTG_STATE_B_IDLE;
		} else if (iotg->hsm.a_vbus_vld) {
			langwell_otg_del_timer(a_wait_vrise_tmr);
			iotg->hsm.b_conn = 0;
			if (lnw->iotg.start_host)
				lnw->iotg.start_host(&lnw->iotg);
			else {
				dev_dbg(lnw->dev, "host driver not loaded.\n");
				break;
			}

			langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
			iotg->otg.state = OTG_STATE_A_WAIT_BCON;
		} else if (iotg->hsm.a_wait_vrise_tmout) {
			iotg->hsm.b_conn = 0;
			if (iotg->hsm.a_vbus_vld) {
				if (lnw->iotg.start_host)
					lnw->iotg.start_host(&lnw->iotg);
				else {
					dev_dbg(lnw->dev,
						"host driver not loaded.\n");
					break;
				}
				langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
				iotg->otg.state = OTG_STATE_A_WAIT_BCON;
			} else {

				/* Turn off VBus */
				iotg->otg.set_vbus(&iotg->otg, false);
				langwell_otg_phy_low_power_wait(1);
				iotg->otg.state = OTG_STATE_A_VBUS_ERR;
			}
		}
		break;
	case OTG_STATE_A_WAIT_BCON:
		if (iotg->hsm.id) {
			/* delete hsm timer for a_wait_bcon_tmr */
			del_timer_sync(&lnw->hsm_timer);

			iotg->otg.default_a = 0;
			iotg->hsm.b_bus_req = 0;

			if (lnw->iotg.stop_host)
				lnw->iotg.stop_host(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"host driver has been removed.\n");

			/* Turn off VBus */
			iotg->otg.set_vbus(&iotg->otg, false);
			set_client_mode();
			langwell_otg_phy_low_power_wait(1);
			iotg->otg.state = OTG_STATE_B_IDLE;
			langwell_update_transceiver();
		} else if (!iotg->hsm.a_vbus_vld) {
			/* delete hsm timer for a_wait_bcon_tmr */
			del_timer_sync(&lnw->hsm_timer);

			if (lnw->iotg.stop_host)
				lnw->iotg.stop_host(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"host driver has been removed.\n");

			/* Turn off VBus */
			iotg->otg.set_vbus(&iotg->otg, false);
			langwell_otg_phy_low_power_wait(1);
			iotg->otg.state = OTG_STATE_A_VBUS_ERR;
		} else if (iotg->hsm.a_bus_drop ||
				(iotg->hsm.a_wait_bcon_tmout &&
				!iotg->hsm.a_bus_req)) {
			/* delete hsm timer for a_wait_bcon_tmr */
			del_timer_sync(&lnw->hsm_timer);

			if (lnw->iotg.stop_host)
				lnw->iotg.stop_host(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"host driver has been removed.\n");

			/* Turn off VBus */
			iotg->otg.set_vbus(&iotg->otg, false);
			iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
		} else if (iotg->hsm.b_conn) {
			/* delete hsm timer for a_wait_bcon_tmr */
			del_timer_sync(&lnw->hsm_timer);

			iotg->hsm.a_suspend_req = 0;
			iotg->otg.state = OTG_STATE_A_HOST;
			if (iotg->hsm.a_srp_det && iotg->otg.host &&
					!iotg->otg.host->b_hnp_enable) {
				/* SRP capable peripheral-only device */
				iotg->hsm.a_bus_req = 1;
				iotg->hsm.a_srp_det = 0;
			} else if (!iotg->hsm.a_bus_req && iotg->otg.host &&
					iotg->otg.host->b_hnp_enable) {
				/* It is not safe enough to do a fast
				 * transistion from A_WAIT_BCON to
				 * A_SUSPEND */
				msleep(10000);
				if (iotg->hsm.a_bus_req)
					break;

				if (request_irq(pdev->irq,
					otg_dummy_irq, IRQF_SHARED,
					driver_name, iotg->base) != 0) {
					dev_dbg(lnw->dev,
						"request interrupt %d fail\n",
						pdev->irq);
				}

				langwell_otg_HABA(1);
				iotg->hsm.b_bus_resume = 0;
				iotg->hsm.a_aidl_bdis_tmout = 0;

				langwell_otg_loc_sof(0);
				/* clear PHCD to enable HW timer */
				langwell_otg_phy_low_power(0);
				langwell_otg_add_timer(a_aidl_bdis_tmr);
				iotg->otg.state = OTG_STATE_A_SUSPEND;
			} else if (!iotg->hsm.a_bus_req && iotg->otg.host &&
				!iotg->otg.host->b_hnp_enable) {
				if (lnw->iotg.stop_host)
					lnw->iotg.stop_host(&lnw->iotg);
				else
					dev_dbg(lnw->dev,
						"host driver removed.\n");

				/* Turn off VBus */
				iotg->otg.set_vbus(&iotg->otg, false);
				iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
			}
		}
		break;
	case OTG_STATE_A_HOST:
		if (iotg->hsm.id) {
			iotg->otg.default_a = 0;
			iotg->hsm.b_bus_req = 0;

			if (lnw->iotg.stop_host)
				lnw->iotg.stop_host(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"host driver has been removed.\n");

			/* Turn off VBus */
			iotg->otg.set_vbus(&iotg->otg, false);
			set_client_mode();
			langwell_otg_phy_low_power_wait(1);
			iotg->otg.state = OTG_STATE_B_IDLE;
			langwell_update_transceiver();
		} else if (iotg->hsm.a_bus_drop ||
				(iotg->otg.host &&
				!iotg->otg.host->b_hnp_enable &&
					!iotg->hsm.a_bus_req)) {
			if (lnw->iotg.stop_host)
				lnw->iotg.stop_host(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"host driver has been removed.\n");

			/* Turn off VBus */
			iotg->otg.set_vbus(&iotg->otg, false);
			iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
		} else if (!iotg->hsm.a_vbus_vld) {
			if (lnw->iotg.stop_host)
				lnw->iotg.stop_host(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"host driver has been removed.\n");

			/* Turn off VBus */
			iotg->otg.set_vbus(&iotg->otg, false);
			langwell_otg_phy_low_power_wait(1);
			iotg->otg.state = OTG_STATE_A_VBUS_ERR;
		} else if (iotg->otg.host &&
				iotg->otg.host->b_hnp_enable &&
				!iotg->hsm.a_bus_req) {
			/* Set HABA to enable hardware assistance to signal
			 *  A-connect after receiver B-disconnect. Hardware
			 *  will then set client mode and enable URE, SLE and
			 *  PCE after the assistance. otg_dummy_irq is used to
			 *  clean these ints when client driver is not resumed.
			 */
			if (request_irq(pdev->irq, otg_dummy_irq, IRQF_SHARED,
					driver_name, iotg->base) != 0) {
				dev_dbg(lnw->dev,
					"request interrupt %d failed\n",
						pdev->irq);
			}

			/* set HABA */
			langwell_otg_HABA(1);
			iotg->hsm.b_bus_resume = 0;
			iotg->hsm.a_aidl_bdis_tmout = 0;
			langwell_otg_loc_sof(0);
			/* clear PHCD to enable HW timer */
			langwell_otg_phy_low_power(0);
			langwell_otg_add_timer(a_aidl_bdis_tmr);
			iotg->otg.state = OTG_STATE_A_SUSPEND;
		} else if (!iotg->hsm.b_conn || !iotg->hsm.a_bus_req) {
			langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
			iotg->otg.state = OTG_STATE_A_WAIT_BCON;
		}
		break;
	case OTG_STATE_A_SUSPEND:
		if (iotg->hsm.id) {
			langwell_otg_del_timer(a_aidl_bdis_tmr);
			langwell_otg_HABA(0);
			free_irq(pdev->irq, iotg->base);
			iotg->otg.default_a = 0;
			iotg->hsm.b_bus_req = 0;

			if (lnw->iotg.stop_host)
				lnw->iotg.stop_host(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"host driver has been removed.\n");

			/* Turn off VBus */
			iotg->otg.set_vbus(&iotg->otg, false);
			set_client_mode();
			langwell_otg_phy_low_power(1);
			iotg->otg.state = OTG_STATE_B_IDLE;
			langwell_update_transceiver();
		} else if (iotg->hsm.a_bus_req ||
				iotg->hsm.b_bus_resume) {
			langwell_otg_del_timer(a_aidl_bdis_tmr);
			langwell_otg_HABA(0);
			free_irq(pdev->irq, iotg->base);
			iotg->hsm.a_suspend_req = 0;
			langwell_otg_loc_sof(1);
			iotg->otg.state = OTG_STATE_A_HOST;
		} else if (iotg->hsm.a_aidl_bdis_tmout ||
				iotg->hsm.a_bus_drop) {
			langwell_otg_del_timer(a_aidl_bdis_tmr);
			langwell_otg_HABA(0);
			free_irq(pdev->irq, iotg->base);
			if (lnw->iotg.stop_host)
				lnw->iotg.stop_host(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"host driver has been removed.\n");

			/* Turn off VBus */
			iotg->otg.set_vbus(&iotg->otg, false);
			iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
		} else if (!iotg->hsm.b_conn && iotg->otg.host &&
				iotg->otg.host->b_hnp_enable) {
			langwell_otg_del_timer(a_aidl_bdis_tmr);
			langwell_otg_HABA(0);
			free_irq(pdev->irq, iotg->base);

			if (lnw->iotg.stop_host)
				lnw->iotg.stop_host(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"host driver has been removed.\n");

			iotg->hsm.b_bus_suspend = 0;
			iotg->hsm.b_bus_suspend_vld = 0;

			/* msleep(200); */
			if (lnw->iotg.start_peripheral)
				lnw->iotg.start_peripheral(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"client driver not loaded.\n");

			langwell_otg_add_ktimer(TB_BUS_SUSPEND_TMR);
			iotg->otg.state = OTG_STATE_A_PERIPHERAL;
			break;
		} else if (!iotg->hsm.a_vbus_vld) {
			langwell_otg_del_timer(a_aidl_bdis_tmr);
			langwell_otg_HABA(0);
			free_irq(pdev->irq, iotg->base);
			if (lnw->iotg.stop_host)
				lnw->iotg.stop_host(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"host driver has been removed.\n");

			/* Turn off VBus */
			iotg->otg.set_vbus(&iotg->otg, false);
			langwell_otg_phy_low_power_wait(1);
			iotg->otg.state = OTG_STATE_A_VBUS_ERR;
		}
		break;
	case OTG_STATE_A_PERIPHERAL:
		if (iotg->hsm.id) {
			/* delete hsm timer for b_bus_suspend_tmr */
			del_timer_sync(&lnw->hsm_timer);
			iotg->otg.default_a = 0;
			iotg->hsm.b_bus_req = 0;
			if (lnw->iotg.stop_peripheral)
				lnw->iotg.stop_peripheral(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"client driver has been removed.\n");

			/* Turn off VBus */
			iotg->otg.set_vbus(&iotg->otg, false);
			set_client_mode();
			langwell_otg_phy_low_power_wait(1);
			iotg->otg.state = OTG_STATE_B_IDLE;
			langwell_update_transceiver();
		} else if (!iotg->hsm.a_vbus_vld) {
			/* delete hsm timer for b_bus_suspend_tmr */
			del_timer_sync(&lnw->hsm_timer);

			if (lnw->iotg.stop_peripheral)
				lnw->iotg.stop_peripheral(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"client driver has been removed.\n");

			/* Turn off VBus */
			iotg->otg.set_vbus(&iotg->otg, false);
			langwell_otg_phy_low_power_wait(1);
			iotg->otg.state = OTG_STATE_A_VBUS_ERR;
		} else if (iotg->hsm.a_bus_drop) {
			/* delete hsm timer for b_bus_suspend_tmr */
			del_timer_sync(&lnw->hsm_timer);

			if (lnw->iotg.stop_peripheral)
				lnw->iotg.stop_peripheral(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"client driver has been removed.\n");

			/* Turn off VBus */
			iotg->otg.set_vbus(&iotg->otg, false);
			iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
		} else if (iotg->hsm.b_bus_suspend) {
			/* delete hsm timer for b_bus_suspend_tmr */
			del_timer_sync(&lnw->hsm_timer);

			if (lnw->iotg.stop_peripheral)
				lnw->iotg.stop_peripheral(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"client driver has been removed.\n");

			if (lnw->iotg.start_host)
				lnw->iotg.start_host(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
						"host driver not loaded.\n");
			langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
			iotg->otg.state = OTG_STATE_A_WAIT_BCON;
		} else if (iotg->hsm.b_bus_suspend_tmout) {
			u32	val;
			val = readl(lnw->iotg.base + CI_PORTSC1);
			if (!(val & PORTSC_SUSP))
				break;

			if (lnw->iotg.stop_peripheral)
				lnw->iotg.stop_peripheral(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
					"client driver has been removed.\n");

			if (lnw->iotg.start_host)
				lnw->iotg.start_host(&lnw->iotg);
			else
				dev_dbg(lnw->dev,
						"host driver not loaded.\n");
			langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
			iotg->otg.state = OTG_STATE_A_WAIT_BCON;
		}
		break;
	case OTG_STATE_A_VBUS_ERR:
		if (iotg->hsm.id) {
			iotg->otg.default_a = 0;
			iotg->hsm.a_clr_err = 0;
			iotg->hsm.a_srp_det = 0;
			set_client_mode();
			langwell_otg_phy_low_power(1);
			iotg->otg.state = OTG_STATE_B_IDLE;
			langwell_update_transceiver();
		} else if (iotg->hsm.a_clr_err) {
			iotg->hsm.a_clr_err = 0;
			iotg->hsm.a_srp_det = 0;
			reset_otg();
			init_hsm();
			if (iotg->otg.state == OTG_STATE_A_IDLE)
				langwell_update_transceiver();
		} else {
			/* FW will clear PHCD bit when any VBus
			 * event detected. Reset PHCD to 1 again */
			langwell_otg_phy_low_power(1);
		}
		break;
	case OTG_STATE_A_WAIT_VFALL:
		if (iotg->hsm.id) {
			iotg->otg.default_a = 0;
			set_client_mode();
			langwell_otg_phy_low_power(1);
			iotg->otg.state = OTG_STATE_B_IDLE;
			langwell_update_transceiver();
		} else if (iotg->hsm.a_bus_req) {

			/* Turn on VBus */
			iotg->otg.set_vbus(&iotg->otg, true);
			iotg->hsm.a_wait_vrise_tmout = 0;
			langwell_otg_add_timer(a_wait_vrise_tmr);
			iotg->otg.state = OTG_STATE_A_WAIT_VRISE;
		} else if (!iotg->hsm.a_sess_vld) {
			iotg->hsm.a_srp_det = 0;
			set_host_mode();
			langwell_otg_phy_low_power(1);
			iotg->otg.state = OTG_STATE_A_IDLE;
		}
		break;
	default:
		;
	}

	dev_dbg(lnw->dev, "%s: new state = %s\n", __func__,
			state_string(iotg->otg.state));
}

Generated by GNU enscript 1.6.4.