int dwc3_intel_byt_resume(struct dwc_otg2 *otg) { struct pci_dev *pci_dev; if (!otg) return 0; pci_dev = to_pci_dev(otg->dev); /* From synopsys spec 12.2.11. * Software cannot access memory-mapped I/O space * for 10ms. */ mdelay(10); pci_restore_state(pci_dev); if (pci_enable_device(pci_dev) < 0) { otg_err(otg, "pci_enable_device failed.\n"); return -EIO; } set_sus_phy(otg, 0); return 0; }
int dwc3_intel_platform_init(struct dwc_otg2 *otg) { int retval; struct intel_dwc_otg_pdata *data; data = (struct intel_dwc_otg_pdata *)otg->otg_data; /* Init a_bus_drop callback */ otg->usb2_phy.a_bus_drop = dwc_a_bus_drop; otg->usb2_phy.vbus_state = VBUS_ENABLED; /* Get usb2 phy type */ otg->usb2_phy.intf = data->usb2_phy_type; /* Turn off VUSBPHY if it haven't used by USB2 PHY. * Otherwise, it will consume ~2.6mA(on VSYS) on MOFD. */ if (!data->using_vusbphy) { retval = control_usb_phy_power(PMIC_VLDOCNT, false); if (retval) otg_err(otg, "Fail to turn off VUSBPHY\n"); } else if (!is_utmi_phy(otg)) { /* If the current USB2 PHY low power controlled by VUSBPHY. Then * we need to de-assert USBRST pin to make USB2 PHY always stay * in active state. */ retval = control_usb_phy_power(PMIC_USBPHYCTRL, true); if (retval) otg_err(otg, "Fail to de-assert USBRST#\n"); } else { /* If we are using utmi phy, and through VUSBPHY to do power * control. Then we need to assert USBRST# for external ULPI phy * to ask it under inactive state saving power. */ retval = control_usb_phy_power(PMIC_USBPHYCTRL, false); if (retval) otg_err(otg, "Fail to de-assert USBRST#\n"); } /* Don't let phy go to suspend mode, which * will cause FS/LS devices enum failed in host mode. */ set_sus_phy(otg, 0); retval = device_create_file(otg->dev, &dev_attr_otg_id); if (retval < 0) { otg_dbg(otg, "Can't register sysfs attribute: %d\n", retval); return -ENOMEM; } otg_dbg(otg, "\n"); otg_write(otg, OEVTEN, 0); otg_write(otg, OCTL, 0); dwc3_switch_mode(otg, GCTL_PRT_CAP_DIR_OTG); return 0; }
int dwc3_intel_byt_suspend(struct dwc_otg2 *otg) { struct pci_dev *pci_dev; pci_power_t state = PCI_D3hot; if (!otg) return 0; pci_dev = to_pci_dev(otg->dev); set_sus_phy(otg, 1); if (pci_save_state(pci_dev)) { otg_err(otg, "pci_save_state failed!\n"); return -EIO; } pci_disable_device(pci_dev); pci_set_power_state(pci_dev, state); return 0; }
int dwc3_intel_byt_platform_init(struct dwc_otg2 *otg) { struct intel_dwc_otg_pdata *data; u32 gctl; int id_value; int retval; data = (struct intel_dwc_otg_pdata *)otg->otg_data; if (data) INIT_DELAYED_WORK(&data->suspend_discon_work, dwc_otg_suspend_discon_work); if (data && data->gpio_cs && data->gpio_reset) { retval = gpio_request(data->gpio_cs, "phy_cs"); if (retval < 0) { otg_err(otg, "failed to request CS pin %d\n", data->gpio_cs); return retval; } retval = gpio_request(data->gpio_reset, "phy_reset"); if (retval < 0) { otg_err(otg, "failed to request RESET pin %d\n", data->gpio_reset); return retval; } } if (data && data->gpio_id) { dev_info(otg->dev, "USB ID detection - Enabled - GPIO\n"); /* Set ID default value to 1 Floating */ data->id = 1; retval = gpio_request(data->gpio_id, "gpio_id"); if (retval < 0) { otg_err(otg, "failed to request ID pin %d\n", data->gpio_id); return retval; } retval = gpio_direction_input(data->gpio_id); if (retval < 0) { otg_err(otg, "failed to request ID pin %d\n", data->gpio_id); return retval; } retval = request_threaded_irq(gpio_to_irq(data->gpio_id), NULL, dwc3_gpio_id_irq, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT, "dwc-gpio-id", otg->dev); if (retval < 0) { otg_err(otg, "failed to request interrupt gpio ID\n"); return retval; } otg_dbg(otg, "GPIO ID request/Interrupt reuqest Done\n"); id_value = dwc3_check_gpio_id(otg); if ((id_value == 0 || id_value == 1) && (data->id != id_value)) { data->id = id_value; dev_info(otg->dev, "ID notification (id = %d)\n", data->id); atomic_notifier_call_chain(&otg->usb2_phy.notifier, USB_EVENT_ID, &id_value); } else otg_dbg(otg, "Get incorrect ID value %d\n", id_value); } /* Don't let phy go to suspend mode, which * will cause FS/LS devices enum failed in host mode. */ set_sus_phy(otg, 0); retval = device_create_file(otg->dev, &dev_attr_otg_id); if (retval < 0) { otg_dbg(otg, "Can't register sysfs attribute: %d\n", retval); return -ENOMEM; } retval = device_create_file(otg->dev, &dev_attr_vbus_evt); if (retval < 0) { otg_dbg(otg, "Can't register sysfs attribute: %d\n", retval); return -ENOMEM; } otg_dbg(otg, "\n"); otg_write(otg, OEVTEN, 0); otg_write(otg, OCTL, 0); gctl = otg_read(otg, GCTL); gctl |= GCTL_PRT_CAP_DIR_OTG << GCTL_PRT_CAP_DIR_SHIFT; otg_write(otg, GCTL, gctl); return 0; }
int dwc3_intel_resume(struct dwc_otg2 *otg) { struct pci_dev *pci_dev; struct usb_hcd *hcd = NULL; u32 data; int ret; if (!otg) return 0; hcd = container_of(otg->otg.host, struct usb_hcd, self); /* After resume from D0i3cold. The UTMI PHY D+ drive issue * reproduced due to all setting be reseted. So switch to OTG * mode avoid D+ drive too early. */ if ((otg->state == DWC_STATE_B_IDLE || otg->state == DWC_STATE_CHARGING || otg->state == DWC_STATE_WAIT_VBUS_FALL || otg->state == DWC_STATE_WAIT_VBUS_RAISE) && is_utmi_phy(otg)) { /* Reconnect DP/DM between Pmic and SOC for support host * and device mode. */ ret = intel_scu_ipc_update_register(PMIC_USBPHYCTRL, USBPHYRSTB, USBPHYRSTB); if (ret) otg_err(otg, "%s: ipc update failed\n", __func__); otg_write(otg, OEVTEN, 0); otg_write(otg, OCTL, 0); dwc3_switch_mode(otg, GCTL_PRT_CAP_DIR_OTG); } /* This is one SCU WA. SCU should set GUSB2PHYCFG0 * bit 4 for ULPI setting. But SCU haven't do that. * So do WA first until SCU fix. */ data = otg_read(otg, GUSB2PHYCFG0); if (is_utmi_phy(otg)) data &= ~(1 << 4); else data |= (1 << 4); otg_write(otg, GUSB2PHYCFG0, data); pci_dev = to_pci_dev(otg->dev); /* From synopsys spec 12.2.11. * Software cannot access memory-mapped I/O space * for 10ms. Delay 5 ms here should be enough. Too * long a delay causes hibernation exit failure. */ mdelay(5); pci_restore_state(pci_dev); if (pci_enable_device(pci_dev) < 0) { otg_err(otg, "pci_enable_device failed.\n"); return -EIO; } set_sus_phy(otg, 0); /* Delay 1ms waiting PHY clock debounce. * Without this debounce, will met fabric error randomly. **/ mdelay(1); if (otg->state == DWC_STATE_A_HOST && otg->resume_host) otg->resume_host(hcd); return 0; }
int dwc3_intel_suspend(struct dwc_otg2 *otg) { int ret; struct usb_phy *phy; struct pci_dev *pci_dev; struct usb_hcd *hcd = NULL; pci_power_t state = PCI_D3cold; if (!otg) return 0; hcd = container_of(otg->otg.host, struct usb_hcd, self); pci_dev = to_pci_dev(otg->dev); if (otg->state == DWC_STATE_A_HOST && otg->suspend_host) { /* Check if USB2 ULPI PHY is hang via access its internal * registers. If hang, then do hard reset before enter * hibernation mode. Otherwise, the USB2 PHY can't enter * suspended state which will blocking U2PMU can't get ready * then can't enter D0i3hot forever in SCU FW. */ if (!is_utmi_phy(otg)) { phy = usb_get_phy(USB_PHY_TYPE_USB2); if (!phy) return -ENODEV; if (usb_phy_io_read(phy, ULPI_VENDOR_ID_LOW) < 0) { enable_usb_phy(otg, 0); enable_usb_phy(otg, 1); } usb_put_phy(phy); } ret = otg->suspend_host(hcd); if (ret) { otg_err(otg, "dwc3-host enter suspend faield: %d\n", ret); return ret; } } if (otg->state == DWC_STATE_B_PERIPHERAL || otg->state == DWC_STATE_A_HOST) state = PCI_D3hot; set_sus_phy(otg, 1); if (pci_save_state(pci_dev)) { otg_err(otg, "pci_save_state failed!\n"); return -EIO; } pci_disable_device(pci_dev); if ((state == PCI_D3cold) && is_utmi_phy(otg)) { /* Important!! Whenever the VUSBPHY rail is disabled, SW * must assert USBRST# to isolate the SOC’s DP/DM pins from the * outside world. There is a risk of damage to the SOC if a * peripheral were to bias DP/DM to 3.3V when the SOC is * unpowered. */ ret = intel_scu_ipc_update_register(PMIC_USBPHYCTRL, 0x0, USBPHYRSTB); if (ret) otg_err(otg, "%s: ipc update failed\n", __func__); } pci_set_power_state(pci_dev, state); return 0; }