static int msm_hsphy_set_params(struct usb_phy *uphy) { struct msm_hsphy *phy = container_of(uphy, struct msm_hsphy, phy); bool host = uphy->flags & PHY_HOST_MODE; int hsphy_init_seq; /* * write HSPHY init value to QSCRATCH reg to set HSPHY parameters like * VBUS valid threshold, disconnect valid threshold, DC voltage level, * preempasis and rise/fall time. */ if (host) { if (override_phy_init_host) phy->hsphy_init_seq_host = override_phy_init_host; hsphy_init_seq = phy->hsphy_init_seq_host; } else { if (override_phy_init) phy->hsphy_init_seq = override_phy_init; hsphy_init_seq = phy->hsphy_init_seq; } if (!hsphy_init_seq) return 0; dev_info(uphy->dev, "set phy param for %s value=0x%08x\n", host ? "host" : "peripheral", hsphy_init_seq & 0x03FFFFFF); msm_usb_write_readback(phy->base, PARAMETER_OVERRIDE_X_REG(0), 0x03FFFFFF, hsphy_init_seq & 0x03FFFFFF); msm_hsphy_param_output(uphy); return 0; }
static int msm_hsphy_init(struct usb_phy *uphy) { struct msm_hsphy *phy = container_of(uphy, struct msm_hsphy, phy); u32 val; msm_hsphy_reset(uphy); /* different sequences based on core version */ phy->core_ver = readl_relaxed(phy->base); /* * HSPHY Initialization: Enable UTMI clock and clamp enable HVINTs, * and disable RETENTION (power-on default is ENABLED) */ val = readl_relaxed(phy->base + HS_PHY_CTRL_REG(0)); val |= (USB2_UTMI_CLK_EN | CLAMP_MPM_DPSE_DMSE_EN_N | RETENABLEN); if (uphy->flags & ENABLE_SECONDARY_PHY) { val &= ~(USB2_UTMI_CLK_EN | FREECLOCK_SEL); val |= FREECLK_DIS_WHEN_SUSP; } writel_relaxed(val, phy->base + HS_PHY_CTRL_REG(0)); usleep_range(2000, 2200); if (uphy->flags & ENABLE_SECONDARY_PHY) msm_usb_write_readback(phy->base, GENERAL_CFG_REG, SEC_UTMI_FREE_CLK_GFM_SEL1, SEC_UTMI_FREE_CLK_GFM_SEL1); if (phy->core_ver >= MSM_CORE_VER_120) { val = readl_relaxed(phy->base + HS_PHY_CTRL_COMMON_REG); val |= COMMON_OTGDISABLE0 | COMMON_OTGTUNE0_DEFAULT | COMMON_COMMONONN | FSEL_DEFAULT | COMMON_RETENABLEN; if (phy->set_pllbtune) { val |= COMMON_PLLBTUNE | COMMON_CLKCORE; val &= ~COMMON_FSEL; } writel_relaxed(val, phy->base + HS_PHY_CTRL_COMMON_REG); } /* * write HSPHY init value to QSCRATCH reg to set HSPHY parameters like * VBUS valid threshold, disconnect valid threshold, DC voltage level, * preempasis and rise/fall time. */ if (override_phy_init) phy->hsphy_init_seq = override_phy_init; if (phy->hsphy_init_seq) msm_usb_write_readback(phy->base, PARAMETER_OVERRIDE_X_REG(0), 0x03FFFFFF, phy->hsphy_init_seq & 0x03FFFFFF); return 0; }
/* * write HSPHY init value to QSCRATCH reg to set HSPHY * parameters like VBUS valid threshold, disconnect valid * threshold, DC voltage level,preempasis and rise/fall time */ static int msm_hsphy_set_params(struct usb_phy *uphy) { struct msm_hsphy *phy = container_of(uphy, struct msm_hsphy, phy); bool host = uphy->flags & PHY_HOST_MODE; int seq = 0; if (override_phy_init) { seq = override_phy_init; } else if (host && phy->hsphy_host_init_seq) { seq = phy->hsphy_host_init_seq; } else { seq = phy->hsphy_init_seq; } if (seq) { dev_dbg(uphy->dev, "set param to = 0x%x\n", seq); msm_usb_write_readback(phy->base, PARAMETER_OVERRIDE_X_REG(0), 0x03FFFFFF, seq & 0x03FFFFFF); } return 0; }
static int msm_hsphy_set_suspend(struct usb_phy *uphy, int suspend) { struct msm_hsphy *phy = container_of(uphy, struct msm_hsphy, phy); bool host = uphy->flags & PHY_HOST_MODE; bool chg_connected = uphy->flags & PHY_CHARGER_CONNECTED; int i, count; if (!!suspend == phy->suspended) { dev_dbg(uphy->dev, "%s\n", suspend ? "already suspended" : "already resumed"); return 0; } if (suspend) { for (i = 0; i < phy->num_ports; i++) { /* Clear interrupt latch register */ writel_relaxed(ALT_INTERRUPT_MASK, phy->base + HS_PHY_IRQ_STAT_REG(i)); /* Enable DP and DM HV interrupts */ if (phy->core_ver >= MSM_CORE_VER_120) msm_usb_write_readback(phy->base, ALT_INTERRUPT_EN_REG(i), (LINESTATE_INTEN | DPINTEN | DMINTEN), (LINESTATE_INTEN | DPINTEN | DMINTEN)); else msm_usb_write_readback(phy->base, ALT_INTERRUPT_EN_REG(i), DPDMHV_INT_MASK, DPDMHV_INT_MASK); if (!host) { /* set the following: * OTGDISABLE0=1 * USB2_SUSPEND_N_SEL=1, USB2_SUSPEND_N=0 */ if (phy->core_ver >= MSM_CORE_VER_120) msm_usb_write_readback(phy->base, HS_PHY_CTRL_COMMON_REG, COMMON_OTGDISABLE0, COMMON_OTGDISABLE0); else msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(i), OTGDISABLE0, OTGDISABLE0); msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(i), (USB2_SUSPEND_N_SEL | USB2_SUSPEND_N), USB2_SUSPEND_N_SEL); } if (!phy->ext_vbus_id) /* Enable PHY-based IDHV and *OTGSESSVLD HV interrupts */ msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(i), (OTGSESSVLDHV_INTEN | IDHV_INTEN), (OTGSESSVLDHV_INTEN | IDHV_INTEN)); } /* Enable PHY retention */ if (!host && !chg_connected) { if (phy->core_ver == MSM_CORE_VER_120 && phy->set_pllbtune) /* * On this particular revision the PLLITUNE[1] * bit acts as the control for the RETENABLEN * PHY signal. */ msm_usb_write_readback(phy->base, HS_PHY_CTRL_COMMON_REG, COMMON_PLLITUNE_1, COMMON_PLLITUNE_1); else if (phy->core_ver >= MSM_CORE_VER_120) msm_usb_write_readback(phy->base, HS_PHY_CTRL_COMMON_REG, COMMON_RETENABLEN, 0); else msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(0), RETENABLEN, 0); if (phy->csr) { /* switch PHY control to USB2PHY CSRs */ msm_usb_write_readback(phy->csr, USB2PHY_USB_PHY_CFG0, USB2PHY_OVERRIDE_EN, USB2PHY_OVERRIDE_EN); /* clear suspend_n */ msm_usb_write_readback(phy->csr, USB2PHY_HS_PHY_CTRL2, USB2PHY_SUSPEND_N_SEL | USB2PHY_SUSPEND_N, USB2PHY_SUSPEND_N_SEL); /* enable retention */ msm_usb_write_readback(phy->csr, USB2PHY_HS_PHY_CTRL_COMMON0, USB2PHY_COMMONONN | USB2PHY_RETENABLEN, 0); /* disable internal ref clock buffer */ msm_usb_write_readback(phy->csr, USB2PHY_USB_PHY_REFCLK_CTRL, REFCLK_RXTAP_EN, 0); /* power down PHY */ msm_usb_write_readback(phy->csr, USB2PHY_USB_PHY_PWRDOWN_CTRL, PWRDN_B, 0); } phy->lpm_flags |= PHY_RETENTIONED; } /* can turn off regulators if disconnected in device mode */ if (phy->lpm_flags & PHY_RETENTIONED && !phy->cable_connected) { if (phy->ext_vbus_id) { msm_hsusb_ldo_enable(phy, 0); phy->lpm_flags |= PHY_PWR_COLLAPSED; } msm_hsusb_config_vdd(phy, 0); } count = atomic_dec_return(&hsphy_active_count); if (count < 0) { dev_WARN(uphy->dev, "hsphy_active_count=%d, something wrong?\n", count); atomic_set(&hsphy_active_count, 0); } } else { atomic_inc(&hsphy_active_count); if (phy->lpm_flags & PHY_RETENTIONED && !phy->cable_connected) { msm_hsusb_config_vdd(phy, 1); if (phy->ext_vbus_id) { msm_hsusb_ldo_enable(phy, 1); phy->lpm_flags &= ~PHY_PWR_COLLAPSED; } if (phy->csr) { /* power on PHY */ msm_usb_write_readback(phy->csr, USB2PHY_USB_PHY_PWRDOWN_CTRL, PWRDN_B, PWRDN_B); /* enable internal ref clock buffer */ msm_usb_write_readback(phy->csr, USB2PHY_USB_PHY_REFCLK_CTRL, REFCLK_RXTAP_EN, REFCLK_RXTAP_EN); /* disable retention */ msm_usb_write_readback(phy->csr, USB2PHY_HS_PHY_CTRL_COMMON0, USB2PHY_COMMONONN | USB2PHY_RETENABLEN, USB2PHY_COMMONONN | USB2PHY_RETENABLEN); /* switch suspend_n_sel back to HW */ msm_usb_write_readback(phy->csr, USB2PHY_HS_PHY_CTRL2, USB2PHY_SUSPEND_N_SEL | USB2PHY_SUSPEND_N, 0); msm_usb_write_readback(phy->csr, USB2PHY_USB_PHY_CFG0, USB2PHY_OVERRIDE_EN, 0); } /* Disable PHY retention */ if (phy->core_ver == MSM_CORE_VER_120 && phy->set_pllbtune) msm_usb_write_readback(phy->base, HS_PHY_CTRL_COMMON_REG, COMMON_PLLITUNE_1, 0); else if (phy->core_ver >= MSM_CORE_VER_120) msm_usb_write_readback(phy->base, HS_PHY_CTRL_COMMON_REG, COMMON_RETENABLEN, COMMON_RETENABLEN); else msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(0), RETENABLEN, RETENABLEN); phy->lpm_flags &= ~PHY_RETENTIONED; } if (phy->core_ver >= MSM_CORE_VER_120) { if (phy->set_pllbtune) { msm_usb_write_readback(phy->base, HS_PHY_CTRL_COMMON_REG, FSEL_MASK, 0); } else { msm_usb_write_readback(phy->base, HS_PHY_CTRL_COMMON_REG, FSEL_MASK, FSEL_DEFAULT); } } for (i = 0; i < phy->num_ports; i++) { if (!phy->ext_vbus_id) /* Disable HV interrupts */ msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(i), (OTGSESSVLDHV_INTEN | IDHV_INTEN), 0); /* Clear interrupt latch register */ writel_relaxed(ALT_INTERRUPT_MASK, phy->base + HS_PHY_IRQ_STAT_REG(i)); /* Disable DP and DM HV interrupt */ if (phy->core_ver >= MSM_CORE_VER_120) msm_usb_write_readback(phy->base, ALT_INTERRUPT_EN_REG(i), LINESTATE_INTEN, 0); else msm_usb_write_readback(phy->base, ALT_INTERRUPT_EN_REG(i), DPDMHV_INT_MASK, 0); if (!host) { /* Bring PHY out of suspend */ msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(i), USB2_SUSPEND_N_SEL, 0); if (phy->core_ver >= MSM_CORE_VER_120) msm_usb_write_readback(phy->base, HS_PHY_CTRL_COMMON_REG, COMMON_OTGDISABLE0, 0); else msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(i), OTGDISABLE0, 0); } } /* * write HSPHY init value to QSCRATCH reg to set HSPHY * parameters like VBUS valid threshold, disconnect valid * threshold, DC voltage level,preempasis and rise/fall time */ /*++ 2014/11/26 USB Team, PCN00023 ++*/ if (override_phy_init) { phy->hsphy_init_seq = override_phy_init; phy->hsphy_host_init_seq = override_phy_init; } if (!uphy->is_in_host && phy->hsphy_init_seq) { printk("[USB] peripheral mode phy setting\n"); msm_usb_write_readback(phy->base, PARAMETER_OVERRIDE_X_REG(0), 0x03FFFFFF, phy->hsphy_init_seq & 0x03FFFFFF); } if (uphy->is_in_host && phy->hsphy_host_init_seq) { printk("[USB] host mode phy setting\n"); msm_usb_write_readback(phy->base, PARAMETER_OVERRIDE_X_REG(0), 0x03FFFFFF, phy->hsphy_host_init_seq & 0x03FFFFFF); } /*-- 2014/11/26 USB Team, PCN00023 --*/ } phy->suspended = !!suspend; /* double-NOT coerces to bool value */ return 0; }