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);


	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 ||
		#ifdef CONFIG_ZTEMT_COMM_CHARGE
	          dotg->charger->chg_type == DWC3_FLOATED_CHARGER ||
   #endif
			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 = DWC3_IDEV_CHG_MAX;

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

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

	if (dotg->charger->max_power <= 2 && mA > 2) {
		/* Enable charging */
		if (power_supply_set_online(dotg->psy, true))
			goto psy_error;
		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;
		/* Set max current limit */
		if (power_supply_set_current_limit(dotg->psy, 0))
			goto psy_error;
	}

	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;
}
Example #2
0
static void bq24192_irq_worker(struct work_struct *work)
{
	struct bq24192_chip *chip =
		container_of(work, struct bq24192_chip, irq_work);
	union power_supply_propval ret = {0,};
	bool ext_pwr;
	bool wlc_pwr = 0;
	bool chg_done = false;
	u8 temp;
	int rc;
	unsigned long flags;

	wake_lock(&chip->irq_wake_lock);

	msleep(100 * chip->irq_scheduled_time_status);

	rc = bq24192_read_reg(chip->client, SYSTEM_STATUS_REG, &temp);
	/* Open up for next possible interrupt handler beyond read reg
	 * asap, lest we miss an interrupt
	 */
	spin_lock_irqsave(&chip->irq_work_lock, flags);
	chip->irq_scheduled_time_status = 0;
	spin_unlock_irqrestore(&chip->irq_work_lock, flags);

	if (rc) {
		pr_err("failed to read SYSTEM_STATUS_REG rc=%d\n", rc);
		goto irq_worker_exit;
	}

	ext_pwr = !!(temp & PG_STAT_MASK);
	chg_done = (temp & CHARGING_MASK) == 0x30 ? true : false;
	if (chg_done) {
		if (chip->batt_health != POWER_SUPPLY_HEALTH_OVERHEAT &&
				bq24192_get_soc_from_batt_psy(chip) < 100) {
			wake_lock(&chip->extra_chg_lock);
			bq24192_enable_chg_term(chip, false);
			bq24192_trigger_recharge(chip);
			schedule_delayed_work(&chip->extra_chg_work,
					msecs_to_jiffies(EXTRA_CHG_TIME_MS));
		} else {
			if (chip->batt_health != POWER_SUPPLY_HEALTH_OVERHEAT)
				bq24192_set_rechg_voltage(chip, VRECHG_300MV);
			power_supply_changed(&chip->ac_psy);
			pr_info("charge done!!\n");
		}
	}

	if (chip->wlc_psy) {
		chip->wlc_psy->get_property(chip->wlc_psy,
				POWER_SUPPLY_PROP_PRESENT, &ret);
		wlc_pwr = ret.intval;
	}

	if ((chip->ext_pwr ^ ext_pwr) || (chip->wlc_pwr ^ wlc_pwr)) {
		pr_info("power source changed! ext_pwr = %d wlc_pwr = %d\n",
				ext_pwr, wlc_pwr);
		if (wake_lock_active(&chip->icl_wake_lock))
			wake_unlock(&chip->icl_wake_lock);
		if (wake_lock_active(&chip->extra_chg_lock))
			wake_unlock(&chip->extra_chg_lock);
		cancel_delayed_work_sync(&chip->input_limit_work);
		cancel_delayed_work_sync(&chip->therm_work);
		cancel_delayed_work_sync(&chip->extra_chg_work);
		bq24192_enable_chg_term(chip, true);
		bq24192_step_down_detect_disable(chip);
		chip->saved_ibat_ma = 0;
		chip->set_chg_current_ma = chip->chg_current_ma;
		chip->max_input_i_ma = INPUT_CURRENT_LIMIT_MAX_MA;

		if (chip->wlc_psy) {
			if (wlc_pwr && ext_pwr) {
				chip->wlc_pwr = true;
				power_supply_set_online(chip->wlc_psy, true);
			} else if (chip->wlc_pwr && !(ext_pwr && wlc_pwr)) {
				chip->wlc_pwr = false;
				power_supply_set_online(chip->wlc_psy, false);
			}
		}

		if (!wlc_pwr) {
			pr_info("notify vbus to usb otg ext_pwr = %d\n", ext_pwr);
			power_supply_set_present(chip->usb_psy, ext_pwr);
		}

		chip->ext_pwr = ext_pwr;
	}

irq_worker_exit:
	wake_lock_timeout(&chip->irq_wake_lock, 2*HZ);
}
Example #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);


	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 = DWC3_IDEV_CHG_MAX;

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

	dev_info(phy->dev, "Avail curr from USB = %u\n", mA);
    
	if (dotg->charger->max_power <= 2 && mA > 2) {
		/* Enable charging */
		if (power_supply_set_online(dotg->psy, true))
			goto psy_error;
		if (power_supply_set_current_limit(dotg->psy, 1000*mA))
			goto psy_error;
	} else if (dotg->charger->max_power > 0 && (mA == 0 || mA == 2)) {
#if defined(CONFIG_PANTECH_PMIC_CHARGER_SMB347) || defined(CONFIG_PANTECH_PMIC_CHARGER_SMB349) || defined(CONFIG_PANTECH_PMIC_CHARGER_BQ2419X) 
		if(!dotg->dwc->vbus_active) {
			dev_dbg(phy->dev, "%s : charger cable disconnection\n", __func__);
			/* Disable charging */
			if (power_supply_set_online(dotg->psy, false))
				goto psy_error;
			/* Set max current limit */
			if (power_supply_set_current_limit(dotg->psy, 0))
				goto psy_error;
		}
#else
		/* Disable charging */
		if (power_supply_set_online(dotg->psy, false))
			goto psy_error;
		/* Set max current limit */
		if (power_supply_set_current_limit(dotg->psy, 0))
			goto psy_error;
#endif /* defined(CONFIG_PANTECH_PMIC_CHARGER_SMB347) || defined(CONFIG_PANTECH_PMIC_CHARGER_SMB349) */
	}

	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;
}
Example #4
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);
#if defined(CONFIG_DWC3_MSM_BC_12_VZW_SUPPORT) && defined(CONFIG_LGE_PM)
	static bool chglogo_check = false;
#endif

	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;

#ifdef CONFIG_LGE_PM
	if (dotg->charger->chg_type == DWC3_SDP_CHARGER ||
			dotg->charger->chg_type == DWC3_FLOATED_CHARGER)
#else
	if (dotg->charger->chg_type == DWC3_SDP_CHARGER)
#endif
		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_UNKNOWN;

#ifndef CONFIG_LGE_PM
	power_supply_set_supply_type(dotg->psy, power_supply_type);
#endif

#if defined (CONFIG_TOUCHSCREEN_SYNAPTICS_G3) && defined (CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4)
	update_status(1, dotg->charger->chg_type);
#endif

#if defined(CONFIG_DWC3_MSM_BC_12_VZW_SUPPORT) && defined(CONFIG_LGE_PM)
	if (!chglogo_check && lge_get_boot_mode() == LGE_BOOT_MODE_CHARGERLOGO &&
			dotg->charger->chg_type == DWC3_SDP_CHARGER) {
		if (mA > IUNIT)
			chglogo_check = true;
		else if (mA <= 2) {
			dotg->charger->max_power = mA;
			return 0;
		}
	}

	if (mA > 2 && lge_pm_get_cable_type() != NO_INIT_CABLE) {
		if (dotg->charger->chg_type == DWC3_DCP_CHARGER)
			mA = lge_pm_get_ta_current();
	}
#elif defined(CONFIG_LGE_PM)
	if (mA > 2 && lge_pm_get_cable_type() != NO_INIT_CABLE) {
		if (dotg->charger->chg_type == DWC3_SDP_CHARGER) {
			if (dotg->dwc->gadget.speed == USB_SPEED_SUPER) {
				if (dotg->charger->max_power > 2)
					dotg->charger->max_power = 0;
				mA = DWC3_USB30_CHG_CURRENT;
			} else {
				mA = lge_pm_get_usb_current();
			}
#ifdef CONFIG_QPNP_CHARGER
			/* For MST, boost current up over 900mA in spite of USB */
			if (pseudo_batt_info.mode && mA == 500 )
				mA = DWC3_USB30_CHG_CURRENT;
#endif
		} else if (dotg->charger->chg_type == DWC3_DCP_CHARGER) {
			mA = lge_pm_get_ta_current();
		} else if (dotg->charger->chg_type == DWC3_FLOATED_CHARGER) {
			mA = lge_pm_get_usb_current();
		}
	}
#endif

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

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

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

/*                                                                                           */
#ifdef CONFIG_LGE_PM
#ifndef CONFIG_USB_DWC3_LGE_SINGLE_PSY
	if (dwc3_otg_get_psy(phy) < 0)
		goto psy_error;
#else
	if (strcmp(dotg->psy->name, "usb")) {
		pr_info("%s psy name is %s, so change psy to usb.\n", __func__, dotg->psy->name);
		dotg->psy = power_supply_get_by_name("usb");
		if (!dotg->psy)
			goto psy_error;
	}
#endif
	power_supply_set_supply_type(dotg->psy, power_supply_type);
#endif

#if defined(CONFIG_DWC3_MSM_BC_12_VZW_SUPPORT) && defined(CONFIG_LGE_PM)
	if (dotg->charger->max_power <= IUNIT && mA > 2) {
#else
	if (dotg->charger->max_power <= 2 && mA > 2) {
#endif
		/* Enable charging */
		if (power_supply_set_online(dotg->psy, true))
			goto psy_error;
		if (power_supply_set_current_limit(dotg->psy, 1000*mA))
			goto psy_error;
#ifdef CONFIG_QPNP_CHARGER
		if (!strncmp(dotg->psy->name, "ac", 2)) {
			dotg->psy = power_supply_get_by_name("usb");
			if (!dotg->psy)
				goto psy_error;

			if (power_supply_set_online(dotg->psy, true))
				goto psy_error;

			if (power_supply_set_supply_type(dotg->psy, power_supply_type))
				goto psy_error;

			if (power_supply_set_current_limit(dotg->psy, 1000*mA))
				goto psy_error;

			dotg->psy = power_supply_get_by_name("ac");
			if (!dotg->psy)
				goto psy_error;
		}
#endif
	} else if (dotg->charger->max_power > 0 && (mA == 0 || mA == 2)) {
		/* Disable charging */
		if (power_supply_set_online(dotg->psy, false))
			goto psy_error;
		/* Set max current limit */
		if (power_supply_set_current_limit(dotg->psy, 0))
			goto psy_error;

#ifdef CONFIG_QPNP_CHARGER
		if (!strncmp(dotg->psy->name, "ac", 2)) {
			dotg->psy = power_supply_get_by_name("usb");
			if (!dotg->psy)
				goto psy_error;

			if (power_supply_set_online(dotg->psy, false))
				goto psy_error;

			if (power_supply_set_supply_type(dotg->psy, power_supply_type))
				goto psy_error;

			if (power_supply_set_current_limit(dotg->psy, 0))
				goto psy_error;

			dotg->psy = power_supply_get_by_name("ac");
			if (!dotg->psy)
				goto psy_error;
		}
#endif
#ifndef CONFIG_USB_DWC3_LGE_SINGLE_PSY
		dotg->charger->chg_type = DWC3_INVALID_CHARGER;
#endif
	}

	power_supply_changed(dotg->psy);

	dotg->charger->max_power = mA;

#if defined (CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4)
#if defined (CONFIG_TOUCHSCREEN_SYNAPTICS_G2) || defined (CONFIG_MACH_MSM8974_TIGERS)
	queue_work(touch_otg_wq, &dotg->touch_work);
#endif
#endif

	return 0;

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

/* IRQs which OTG driver is interested in handling */
#define DWC3_OEVT_MASK		(DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT | \
				 DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT)

/**
 * dwc3_otg_interrupt - interrupt handler for dwc3 otg events.
 * @_dotg: Pointer to out controller context structure
 *
 * Returns IRQ_HANDLED on success otherwise IRQ_NONE.
 */
static irqreturn_t dwc3_otg_interrupt(int irq, void *_dotg)
{
	struct dwc3_otg *dotg = (struct dwc3_otg *)_dotg;
	u32 osts, oevt_reg;
	int ret = IRQ_NONE;
	int handled_irqs = 0;
	struct usb_phy *phy = dotg->otg.phy;

	oevt_reg = dwc3_readl(dotg->regs, DWC3_OEVT);

	if (!(oevt_reg & DWC3_OEVT_MASK))
		return IRQ_NONE;

	osts = dwc3_readl(dotg->regs, DWC3_OSTS);

	if ((oevt_reg & DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT) ||
	    (oevt_reg & DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT)) {
		/*
		 * ID sts has changed, set inputs later, in the workqueue
		 * function, switch from A to B or from B to A.
		 */

		if (oevt_reg & DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT) {
			if (osts & DWC3_OTG_OSTS_CONIDSTS) {
				dev_dbg(phy->dev, "ID set\n");
				set_bit(ID, &dotg->inputs);
			} else {
				dev_dbg(phy->dev, "ID clear\n");
				clear_bit(ID, &dotg->inputs);
			}
			handled_irqs |= DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT;
		}

		if (oevt_reg & DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT) {
			if (osts & DWC3_OTG_OSTS_BSESVALID) {
				dev_dbg(phy->dev, "BSV set\n");
				set_bit(B_SESS_VLD, &dotg->inputs);
			} else {
				dev_dbg(phy->dev, "BSV clear\n");
				clear_bit(B_SESS_VLD, &dotg->inputs);
			}
			handled_irqs |= DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT;
		}

		queue_delayed_work(system_nrt_wq, &dotg->sm_work, 0);

		ret = IRQ_HANDLED;

		/* Clear the interrupts we handled */
		dwc3_writel(dotg->regs, DWC3_OEVT, handled_irqs);
	}

	return ret;
}

/**
 * dwc3_otg_init_sm - initialize OTG statemachine input
 * @dotg: Pointer to the dwc3_otg structure
 *
 */
void dwc3_otg_init_sm(struct dwc3_otg *dotg)
{
	u32 osts = dwc3_readl(dotg->regs, DWC3_OSTS);
	struct usb_phy *phy = dotg->otg.phy;
	struct dwc3_ext_xceiv *ext_xceiv;
	int ret;

	dev_dbg(phy->dev, "Initialize OTG inputs, osts: 0x%x\n", osts);

	/*
	 * VBUS initial state is reported after PMIC
	 * driver initialization. Wait for it.
	 */
	ret = wait_for_completion_timeout(&dotg->dwc3_xcvr_vbus_init, HZ * 5);
	if (!ret) {
		dev_err(phy->dev, "%s: completion timeout\n", __func__);
		/* We can safely assume no cable connected */
		set_bit(ID, &dotg->inputs);
	}

	ext_xceiv = dotg->ext_xceiv;
	dwc3_otg_reset(dotg);
	if (ext_xceiv && !ext_xceiv->otg_capability) {
		if (osts & DWC3_OTG_OSTS_CONIDSTS)
			set_bit(ID, &dotg->inputs);
		else
			clear_bit(ID, &dotg->inputs);

		if (osts & DWC3_OTG_OSTS_BSESVALID)
			set_bit(B_SESS_VLD, &dotg->inputs);
		else
			clear_bit(B_SESS_VLD, &dotg->inputs);
	}
}
/**
 * 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_DCP_CHARGER:
				case DWC3_PROPRIETARY_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_start_peripheral(&dotg->otg,
									1);
					phy->state = OTG_STATE_B_PERIPHERAL;
					work = 1;
/* OPPO 2013-10-05 wangjc Add begin for support non-standard charger, HW_VERSION__12 is dvt */
#ifdef CONFIG_MACH_MSM8974_14001
#if defined(CONFIG_OPPO_DEVICE_FIND7) || defined(CONFIG_OPPO_DEVICE_FIND7WX)
					if(get_pcb_version() < HW_VERSION__12) {
						cancel_delayed_work_sync(&dotg->non_standard_charger_work);
						non_standard = true;

						schedule_delayed_work(&dotg->non_standard_charger_work,
							round_jiffies_relative(msecs_to_jiffies
							(5000)));

					} else {
						/* [email protected], 2014/01/23  Add for notify usb online earlier */
						power_supply_set_online(dotg->psy, true);
						power_supply_changed(dotg->psy);
					}
#else
					power_supply_set_online(dotg->psy, true);
					power_supply_changed(dotg->psy);
#endif
#endif
/* OPPO 2013-10-05 wangjc Add end */
					break;
				case DWC3_FLOATED_CHARGER:
/* OPPO 2013-10-05 wangjc Modify begin for support non-standard charger */
#ifndef CONFIG_MACH_MSM8974_14001
					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) {
						dwc3_otg_set_power(phy, 0);
						pm_runtime_put_sync(phy->dev);
						break;
					}
					charger->start_detection(dotg->charger,
									false);
#else
					dev_dbg(phy->dev, "lpm, FLOATED charger\n");
					dwc3_otg_set_power(phy,
							DWC3_IDEV_CHG_FLOATED);
					pm_runtime_put_sync(phy->dev);
					break;
#endif
/* OPPO 2013-10-05 wangjc Modify end */

				default:
					dev_dbg(phy->dev, "chg_det started\n");
/* OPPO 2013-11-18 wangjc Modify begin for detect charger type later */
#ifndef CONFIG_MACH_MSM8974_14001
					charger->start_detection(charger, true);
#else
					/* [email protected], 2014/02/24  Add for solve usb reboot problem */
					cancel_delayed_work_sync(&dotg->detect_work);
					/* [email protected], 2014/03/25  Add for solve usb reboot problem,bug 422328 */
					if (charger)
						charger->start_detection(dotg->charger, false);

					dotg->charger_retry_count = 0;
					dwc3_otg_set_power(phy, 0);
					
					queue_delayed_work(system_nrt_wq, &dotg->detect_work, msecs_to_jiffies(600));
#endif
/* OPPO 2013-11-18 wangjc Modify end */
					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 {
/* OPPO 2013-12-01 wangjc Add begin for for non standard charger detect, HW_VERSION__12 is dvt */
#ifdef CONFIG_MACH_MSM8974_14001
//#ifdef CONFIG_OPPO_DEVICE_FIND7
#if defined(CONFIG_OPPO_DEVICE_FIND7) || defined(CONFIG_OPPO_DEVICE_FIND7WX)
			if(get_pcb_version() < HW_VERSION__12) {
				cancel_delayed_work_sync(&dotg->non_standard_charger_work);
			}
#endif
#endif
/* OPPO 2013-12-01 wangjc Add end */
#ifdef CONFIG_MACH_MSM8974_14001
/* [email protected], 2014/01/06  Add for solve usb reboot problem */
			cancel_delayed_work_sync(&dotg->detect_work);
#endif /*CONFIG_MACH_MSM8974_14001*/

			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 (charger)
				charger->chg_type = DWC3_INVALID_CHARGER;
			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;
			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);
}
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);


	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)
		{
#ifdef CONFIG_MACH_MSM8974_14001
        /* [email protected], 2015/03/20,  Modify for some usb3.0 port detected as  USB_CDP ,can not show charge icon when charge */
		power_supply_type = POWER_SUPPLY_TYPE_USB;
#else
		power_supply_type = POWER_SUPPLY_TYPE_USB_CDP;
		
#endif /*CONFIG_MACH_MSM8974_14001*/
		}
	else if (dotg->charger->chg_type == DWC3_DCP_CHARGER ||
			dotg->charger->chg_type == DWC3_PROPRIETARY_CHARGER || 
			dotg->charger->chg_type == DWC3_FLOATED_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 = DWC3_IDEV_CHG_MAX;
/* OPPO 2013-11-05 wangjc Add begin for enable non standard charging */
#ifdef CONFIG_MACH_MSM8974_14001
	if (dotg->charger->chg_type == DWC3_FLOATED_CHARGER)
		mA = DWC3_IDEV_CHG_FLOATED;
#endif
/* OPPO 2013-11-05 wangjc Add end */

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

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

	if (dotg->charger->max_power <= 2 && mA > 2) {
		/* Enable charging */
		if (power_supply_set_online(dotg->psy, true))
			goto psy_error;
#ifdef CONFIG_MACH_MSM8974_14001
/* [email protected], 2014/06/06  Add for slove it show usb icon when plug in charger */
		if(power_supply_type != POWER_SUPPLY_TYPE_USB) {
			power_supply_set_online(dotg->psy, false);
		}
#endif /*CONFIG_MACH_MSM8974_14001*/
		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 */
/* OPPO 2013-11-20 wangjc Add begin for don't set online to false when usb is still plug in */
#ifdef CONFIG_MACH_MSM8974_14001
		if(power_supply_type != POWER_SUPPLY_TYPE_USB) {
			if (power_supply_set_online(dotg->psy, false))
				goto psy_error;

		/* Set max current limit */
		if (power_supply_set_current_limit(dotg->psy, 0))
			goto psy_error;
		}
#endif
/* OPPO 2013-11-20 wangjc Add end */
	}

	power_supply_changed(dotg->psy);
/* OPPO 2013-12-01 wangjc Add begin for non standard charger detect, HW_VERSION__12 is dvt */
#ifdef CONFIG_MACH_MSM8974_14001
#if defined(CONFIG_OPPO_DEVICE_FIND7) || defined(CONFIG_OPPO_DEVICE_FIND7WX)
	if(get_pcb_version() < HW_VERSION__12) {
		if(mA == 500) {
			non_standard = false;
		}
	}
#endif
#endif
/* OPPO 2013-12-01 wangjc Add end */
	dotg->charger->max_power = mA;
	return 0;

psy_error:
	dev_dbg(phy->dev, "power supply error when setting property\n");
	return -ENXIO;
}
Example #7
0
static int dwc3_otg_set_power(struct usb_phy *phy, unsigned mA)
{
	enum power_supply_property power_supply_type;
	struct dwc3_otg *dotg = container_of(phy->otg, struct dwc3_otg, otg);


	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_INVALID_CHARGER) {
		dev_dbg(phy->dev,
			"SKIP setting power supply type again,chg_type = %d\n",
			dotg->charger->chg_type);
		goto skip_psy_type;
	}

	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_UNKNOWN;

	power_supply_set_supply_type(dotg->psy, power_supply_type);

skip_psy_type:

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

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

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

	if (dotg->charger->max_power > 0 && (mA == 0 || mA == 2)) {
		/* Disable charging */
		if (power_supply_set_online(dotg->psy, false))
			goto psy_error;
	} else {
		/* Enable charging */
		if (power_supply_set_online(dotg->psy, true))
			goto psy_error;
	}

	/* Set max current limit in uA */
	if (power_supply_set_current_limit(dotg->psy, 1000*mA))
		goto psy_error;

	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;
}
Example #8
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;
}
Example #9
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);
#if defined(CONFIG_DWC3_MSM_BC_12_VZW_SUPPORT) && defined(CONFIG_LGE_PM)
	static bool chglogo_check = false;
#endif

	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;

#ifdef CONFIG_LGE_PM
	if (dotg->charger->chg_type == DWC3_SDP_CHARGER ||
			dotg->charger->chg_type == DWC3_FLOATED_CHARGER)
#else
	if (dotg->charger->chg_type == DWC3_SDP_CHARGER)
#endif
		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
#ifdef CONFIG_LGE_PM
		/* [email protected]
		 * healthd get battery psy type at init only.
		 * If cable detach before healthd init,
		 * healthd recognize usb psy as battery type.
		 */
		power_supply_type = POWER_SUPPLY_TYPE_UNKNOWN;
#else
		power_supply_type = POWER_SUPPLY_TYPE_BATTERY;
#endif

#ifndef CONFIG_LGE_PM
	power_supply_set_supply_type(dotg->psy, power_supply_type);
#endif

#if defined (CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4)
	update_status(1, dotg->charger->chg_type);
#endif

#if defined(CONFIG_DWC3_MSM_BC_12_VZW_SUPPORT) && defined(CONFIG_LGE_PM)
	if (!chglogo_check && lge_get_boot_mode() == LGE_BOOT_MODE_CHARGERLOGO &&
			dotg->charger->chg_type == DWC3_SDP_CHARGER) {
		if (mA > IUNIT)
			chglogo_check = true;
		else if (mA <= 2) {
			dotg->charger->max_power = mA;
			return 0;
		}
	}

	if (mA > 2 && lge_pm_get_cable_type() != NO_INIT_CABLE) {
		if (dotg->charger->chg_type == DWC3_DCP_CHARGER)
			mA = lge_pm_get_ta_current();
	}
#elif defined(CONFIG_LGE_PM)
	if (mA > 2 && lge_pm_get_cable_type() != NO_INIT_CABLE) {
		if (dotg->charger->chg_type == DWC3_SDP_CHARGER) {
			if (dotg->dwc->gadget.speed == USB_SPEED_SUPER) {
				if (dotg->charger->max_power > 2)
					dotg->charger->max_power = 0;
				mA = DWC3_USB30_CHG_CURRENT;
			} else {
				mA = lge_pm_get_usb_current();
			}
#ifdef CONFIG_QPNP_CHARGER
			/* For MST, boost current up over 900mA in spite of USB */
			if (pseudo_batt_info.mode && mA == 500 )
				mA = DWC3_USB30_CHG_CURRENT;
#endif
		} else if (dotg->charger->chg_type == DWC3_DCP_CHARGER) {
			mA = lge_pm_get_ta_current();
		} else if (dotg->charger->chg_type == DWC3_FLOATED_CHARGER) {
			mA = lge_pm_get_usb_current();
		}
	}
#endif

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

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

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

/* [email protected] make psy getter and move it above power_supply_type setter. 2014-02-06 */
#ifdef CONFIG_LGE_PM
#ifndef CONFIG_USB_DWC3_LGE_SINGLE_PSY
	if (dwc3_otg_get_psy(phy) < 0)
		goto psy_error;
#else
	if (strcmp(dotg->psy->name, "usb")) {
		pr_info("%s psy name is %s, so change psy to usb.\n", __func__, dotg->psy->name);
		dotg->psy = power_supply_get_by_name("usb");
		if (!dotg->psy)
			goto psy_error;
	}
#endif
	power_supply_set_supply_type(dotg->psy, power_supply_type);
#endif

	if (dotg->charger->max_power <= 2 && mA > 2) {
		/* Enable charging */
		if (power_supply_set_online(dotg->psy, true))
			goto psy_error;
		if (power_supply_set_current_limit(dotg->psy, 1000*mA))
			goto psy_error;
#ifdef CONFIG_QPNP_CHARGER
		if (!strncmp(dotg->psy->name, "ac", 2)) {
			dotg->psy = power_supply_get_by_name("usb");
			if (!dotg->psy)
				goto psy_error;

			if (power_supply_set_online(dotg->psy, true))
				goto psy_error;

			if (power_supply_set_supply_type(dotg->psy, power_supply_type))
				goto psy_error;

			if (power_supply_set_current_limit(dotg->psy, 1000*mA))
				goto psy_error;

			dotg->psy = power_supply_get_by_name("ac");
			if (!dotg->psy)
				goto psy_error;
		}
#endif
	} else if (dotg->charger->max_power > 0 && (mA == 0 || mA == 2)) {
		/* Disable charging */
		if (power_supply_set_online(dotg->psy, false))
			goto psy_error;
		/* Set max current limit */
		if (power_supply_set_current_limit(dotg->psy, 0))
			goto psy_error;

#ifdef CONFIG_QPNP_CHARGER
		if (!strncmp(dotg->psy->name, "ac", 2)) {
			dotg->psy = power_supply_get_by_name("usb");
			if (!dotg->psy)
				goto psy_error;

			if (power_supply_set_online(dotg->psy, false))
				goto psy_error;

			if (power_supply_set_supply_type(dotg->psy, power_supply_type))
				goto psy_error;

			if (power_supply_set_current_limit(dotg->psy, 0))
				goto psy_error;

			dotg->psy = power_supply_get_by_name("ac");
			if (!dotg->psy)
				goto psy_error;
		}
#endif
	}

	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;
}