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__); }
/** * 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); }
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; }