Пример #1
0
static void dwc3_ref_clk_work_func(struct work_struct *work)
{
	struct anx7808_data *td = container_of(work, struct anx7808_data,
						dwc3_ref_clk_work.work);
	bool is_connected = slimport_is_connected();

	if (!td->slimport_connected && is_connected) {
		td->slimport_connected = true;
		dwc3_ref_clk_set(true);
	} else if (td->slimport_connected && !is_connected) {
		td->slimport_connected = false;
		dwc3_ref_clk_set(false);
	} else
		pr_info("%s %s : ignore incorrect irq\n", LOG_TAG, __func__);
}
Пример #2
0
/**
 * dwc3_otg_sm_work - workqueue function.
 *
 * @w: Pointer to the dwc3 otg workqueue
 *
 * NOTE: After any change in phy->state,
 * we must reschdule the state machine.
 */
static void dwc3_otg_sm_work(struct work_struct *w)
{
	struct dwc3_otg *dotg = container_of(w, struct dwc3_otg, sm_work.work);
	struct usb_phy *phy = dotg->otg.phy;
	struct dwc3_charger *charger = dotg->charger;
	bool work = 0;
	int ret = 0;
	unsigned long delay = 0;

	pm_runtime_resume(phy->dev);
	dev_dbg(phy->dev, "%s state\n", otg_state_string(phy->state));

	/* Check OTG state */
	switch (phy->state) {
	case OTG_STATE_UNDEFINED:
		dwc3_otg_init_sm(dotg);
		if (!dotg->psy) {
			dotg->psy = power_supply_get_by_name("usb");

			if (!dotg->psy)
				dev_err(phy->dev,
					 "couldn't get usb power supply\n");
		}

		/* Switch to A or B-Device according to ID / BSV */
		if (!test_bit(ID, &dotg->inputs)) {
			dev_dbg(phy->dev, "!id\n");
			phy->state = OTG_STATE_A_IDLE;
			work = 1;
		} else if (test_bit(B_SESS_VLD, &dotg->inputs)) {
			dev_dbg(phy->dev, "b_sess_vld\n");
			phy->state = OTG_STATE_B_IDLE;
			work = 1;
		} else {
			phy->state = OTG_STATE_B_IDLE;
			dev_dbg(phy->dev, "No device, trying to suspend\n");
			pm_runtime_put_sync(phy->dev);
		}
		break;

	case OTG_STATE_B_IDLE:
		if (!test_bit(ID, &dotg->inputs)) {
			dev_dbg(phy->dev, "!id\n");
			phy->state = OTG_STATE_A_IDLE;
			work = 1;
			dotg->charger_retry_count = 0;
			if (charger) {
				if (charger->chg_type == DWC3_INVALID_CHARGER)
					charger->start_detection(dotg->charger,
									false);
				else
					charger->chg_type =
							DWC3_INVALID_CHARGER;
			}
		} else if (test_bit(B_SESS_VLD, &dotg->inputs)) {
			dev_dbg(phy->dev, "b_sess_vld\n");
			if (charger) {
				/* Has charger been detected? If no detect it */
				switch (charger->chg_type) {
				case DWC3_PROPRIETARY_CHARGER:
#if defined(CONFIG_LGE_PM)
					dwc3_otg_set_power(phy,
							DWC3_IDEV_CHG_PROPRIETARY_MAX);
					pm_runtime_put_sync(phy->dev);
					break;
#endif
				case DWC3_DCP_CHARGER:
					dev_dbg(phy->dev, "lpm, DCP charger\n");
					dwc3_otg_set_power(phy,
							DWC3_IDEV_CHG_MAX);
					pm_runtime_put_sync(phy->dev);
					break;
				case DWC3_CDP_CHARGER:
					dwc3_otg_set_power(phy,
							DWC3_IDEV_CHG_MAX);
					dwc3_otg_start_peripheral(&dotg->otg,
									1);
					phy->state = OTG_STATE_B_PERIPHERAL;
					work = 1;
					break;
				case DWC3_SDP_CHARGER:
					dwc3_otg_set_power(phy,
								IUNIT);
					dwc3_otg_start_peripheral(&dotg->otg,
									1);
					phy->state = OTG_STATE_B_PERIPHERAL;
					work = 1;
					break;
				case DWC3_FLOATED_CHARGER:
					if (dotg->charger_retry_count <
							max_chgr_retry_count)
						dotg->charger_retry_count++;
					/*
					 * In case of floating charger, if
					 * retry count equal to max retry count
					 * notify PMIC about floating charger
					 * and put Hw in low power mode. Else
					 * perform charger detection again by
					 * calling start_detection() with false
					 * and then with true argument.
					 */
					if (dotg->charger_retry_count ==
						max_chgr_retry_count) {
#if defined (CONFIG_SLIMPORT_ANX7816) || defined(CONFIG_SLIMPORT_ANX7808)
						if (slimport_is_connected()) {
							dwc3_otg_set_power(phy, IDEV_CHG_MIN);
							pm_runtime_put_sync(phy->dev);
							break;
						}
#endif
#ifdef CONFIG_LGE_PM
#ifdef CONFIG_DWC3_MSM_BC_12_VZW_SUPPORT
						queue_delayed_work(system_nrt_wq, dotg->charger->drv_check_state_wq, 0);
						dwc3_otg_set_power(phy, IUNIT);
						dwc3_otg_start_peripheral(&dotg->otg, 1);
						phy->state = OTG_STATE_B_PERIPHERAL;
						work = 1;
#else
						dwc3_otg_set_power(phy,	IUNIT);
						dwc3_otg_start_peripheral(&dotg->otg, 1);
						phy->state = OTG_STATE_B_PERIPHERAL;
						work = 1;
#endif
#else
						dwc3_otg_set_power(phy, 0);
						pm_runtime_put_sync(phy->dev);
#endif
						break;
					}
					charger->start_detection(dotg->charger,
									false);

				default:
					dev_dbg(phy->dev, "chg_det started\n");
					charger->start_detection(charger, true);
					break;
				}
			} else {
				/* no charger registered, start peripheral */
				if (dwc3_otg_start_peripheral(&dotg->otg, 1)) {
					/*
					 * Probably set_peripheral not called
					 * yet. We will re-try as soon as it
					 * will be called
					 */
					dev_err(phy->dev, "enter lpm as\n"
						"unable to start B-device\n");
					phy->state = OTG_STATE_UNDEFINED;
					pm_runtime_put_sync(phy->dev);
					return;
				}
			}
		} else {
			if (charger)
				charger->start_detection(dotg->charger, false);

			dotg->charger_retry_count = 0;
			dwc3_otg_set_power(phy, 0);
			dev_dbg(phy->dev, "No device, trying to suspend\n");
			pm_runtime_put_sync(phy->dev);
		}
		break;

	case OTG_STATE_B_PERIPHERAL:
		if (!test_bit(B_SESS_VLD, &dotg->inputs) ||
				!test_bit(ID, &dotg->inputs)) {
			dev_dbg(phy->dev, "!id || !bsv\n");
			dwc3_otg_start_peripheral(&dotg->otg, 0);
			phy->state = OTG_STATE_B_IDLE;
#if defined(CONFIG_DWC3_MSM_CDP_SUPPORT)
			if ((charger) && (charger->chg_type != DWC3_CDP_CHARGER)) {
				charger->chg_type = DWC3_INVALID_CHARGER;
			}
#else
			if (charger)
				charger->chg_type = DWC3_INVALID_CHARGER;
#endif
			work = 1;
		}
		break;

	case OTG_STATE_A_IDLE:
		/* Switch to A-Device*/
		if (test_bit(ID, &dotg->inputs)) {
			dev_dbg(phy->dev, "id\n");
			phy->state = OTG_STATE_B_IDLE;
			dotg->vbus_retry_count = 0;
			work = 1;
		} else {
			phy->state = OTG_STATE_A_HOST;
#ifdef CONFIG_LGE_PM
			/*
                                        
                                                              
    */
			dotg->psy = power_supply_get_by_name("usb");
			if (!dotg->psy)
				dev_err(phy->dev, "couldn't get usb power supply\n");
#endif
			ret = dwc3_otg_start_host(&dotg->otg, 1);
			if ((ret == -EPROBE_DEFER) &&
						dotg->vbus_retry_count < 3) {
				/*
				 * Get regulator failed as regulator driver is
				 * not up yet. Will try to start host after 1sec
				 */
				phy->state = OTG_STATE_A_IDLE;
				dev_dbg(phy->dev, "Unable to get vbus regulator. Retrying...\n");
				delay = VBUS_REG_CHECK_DELAY;
				work = 1;
				dotg->vbus_retry_count++;
			} else if (ret) {
				/*
				 * Probably set_host was not called yet.
				 * We will re-try as soon as it will be called
				 */
				dev_dbg(phy->dev, "enter lpm as\n"
					"unable to start A-device\n");
				phy->state = OTG_STATE_A_IDLE;
				pm_runtime_put_sync(phy->dev);
				return;
			}
		}
		break;

	case OTG_STATE_A_HOST:
		if (test_bit(ID, &dotg->inputs)) {
			dev_dbg(phy->dev, "id\n");
			dwc3_otg_start_host(&dotg->otg, 0);
			phy->state = OTG_STATE_B_IDLE;
			dotg->vbus_retry_count = 0;
			work = 1;
		}
		break;

	default:
		dev_err(phy->dev, "%s: invalid otg-state\n", __func__);

	}

	if (work)
		queue_delayed_work(system_nrt_wq, &dotg->sm_work, delay);
}
Пример #3
0
static int dwc3_otg_set_power(struct usb_phy *phy, unsigned mA)
{
	static int power_supply_type;
	struct dwc3_otg *dotg = container_of(phy->otg, struct dwc3_otg, otg);
	struct power_supply *saved_usb_psy = NULL;
	struct power_supply *ac_psy = NULL;

	if (!dotg->psy || !dotg->charger) {
		dev_err(phy->dev, "no usb power supply/charger registered\n");
		return 0;
	}

	if (dotg->charger->charging_disabled)
		return 0;

	if (dotg->charger->chg_type == DWC3_SDP_CHARGER)
		power_supply_type = POWER_SUPPLY_TYPE_USB;
	else if (dotg->charger->chg_type == DWC3_CDP_CHARGER)
		power_supply_type = POWER_SUPPLY_TYPE_USB_CDP;
	else if (dotg->charger->chg_type == DWC3_DCP_CHARGER ||
			dotg->charger->chg_type == DWC3_PROPRIETARY_CHARGER)
		power_supply_type = POWER_SUPPLY_TYPE_USB_DCP;
	else
		power_supply_type = POWER_SUPPLY_TYPE_BATTERY;

	power_supply_set_supply_type(dotg->psy, power_supply_type);

	if ((dotg->charger->chg_type == DWC3_CDP_CHARGER) && mA > 0)
		mA = DWC3_IDEV_CHG_MAX;

	if (slimport_is_connected() && mA) {
		mA = slimport_get_chg_current();
		if (mA > DWC3_IDEV_CHG_MIN)
			dotg->charger->chg_type = DWC3_DCP_CHARGER;
	}

	if (dotg->charger->max_power == mA)
		return 0;

	dev_info(phy->dev, "Avail curr from USB = %u\n", mA);

	ac_psy = power_supply_get_by_name("ac");

	if (dotg->charger->chg_type == DWC3_DCP_CHARGER && ac_psy) {
		pr_info("%s: override dotg->psy to ac->psy\n", __func__);
		saved_usb_psy = dotg->psy;
		dotg->psy = ac_psy;
	}
	pr_info("dotg->charger->max_power = %d "\
			"ma = %d\n", dotg->charger->max_power, mA);

	if (dotg->charger->max_power <= 2 && mA > 2) {
		/* Enable charging */
		if (power_supply_set_online(dotg->psy, true))
			goto psy_error;
		if (!strcmp(dotg->psy->name, "usb")) {
			if (power_supply_set_current_limit(dotg->psy, 1000*mA))
				goto psy_error;
		}
	} else if (dotg->charger->max_power > 0 && (mA == 0 || mA == 2)) {
		/* Disable charging */
		if (power_supply_set_online(dotg->psy, false))
			goto psy_error;
		if (!strcmp(dotg->psy->name, "usb")) {
			if (power_supply_set_online(ac_psy, false))
				goto psy_error;
			/* Set max current limit */
			if (power_supply_set_current_limit(dotg->psy, 0))
				goto psy_error;
		}
	}

	if (saved_usb_psy)
		dotg->psy = saved_usb_psy;

	power_supply_changed(dotg->psy);
	dotg->charger->max_power = mA;
	return 0;

psy_error:
	dev_dbg(phy->dev, "power supply error when setting property\n");
	return -ENXIO;
}