diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index 342439b1a690..ba327fc3f509 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -102,7 +102,7 @@ struct usb2phy_reg { * @rdm_pdwn_en: open dm pull down resistor. * @vdm_src_en: open dm voltage source. * @vdp_src_en: open dp voltage source. - * @opmode: utmi operational mode. + * @chg_mode: set phy in charge detection mode. */ struct rockchip_chg_det_reg { struct usb2phy_reg cp_det; @@ -114,7 +114,7 @@ struct rockchip_chg_det_reg { struct usb2phy_reg rdm_pdwn_en; struct usb2phy_reg vdm_src_en; struct usb2phy_reg vdp_src_en; - struct usb2phy_reg opmode; + struct usb2phy_reg chg_mode; }; /** @@ -273,6 +273,9 @@ struct rockchip_usb2phy_port { * @chg_type: USB charger types. * @dcd_retries: The retry count used to track Data contact * detection process. + * @primary_retries: The retry count used for charger + * detection primary phase. + * @phy_sus_cfg: Store the phy current suspend configuration. * @edev_self: represent the source of extcon. * @irq: IRQ number assigned for phy which combined irqs of * otg port and host port. @@ -292,6 +295,7 @@ struct rockchip_usb2phy { enum power_supply_type chg_type; u8 dcd_retries; u8 primary_retries; + unsigned int phy_sus_cfg; bool edev_self; int irq; struct extcon_dev *edev; @@ -1201,22 +1205,40 @@ static void rockchip_chg_detect_work(struct work_struct *work) container_of(work, struct rockchip_usb2phy_port, chg_work.work); struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); struct regmap *base = get_reg_base(rphy); + const struct usb2phy_reg *phy_sus_reg; bool is_dcd, tmout, vout; unsigned long delay; + unsigned int mask; + int ret; dev_dbg(&rport->phy->dev, "chg detection work state = %d\n", rphy->chg_state); + /* + * The conditions for charger detection: + * 1. Set the PHY in normal mode to keep the UTMI_CLK on. + * 2. Set the utmi_opmode in non-driving mode. + * 3. Set the utmi_xcvrselect to FS speed. + * 4. Set the utmi_termselect to FS speed. + * 5. Enable the DP/DM pulldown resistor. + */ switch (rphy->chg_state) { case USB_CHG_STATE_UNDEFINED: mutex_lock(&rport->mutex); - if (!rport->suspended) { + /* Store the PHY current suspend configuration */ + phy_sus_reg = &rport->port_cfg->phy_sus; + ret = regmap_read(base, phy_sus_reg->offset, + &rphy->phy_sus_cfg); + if (ret) { + dev_err(&rport->phy->dev, + "Fail to read phy_sus reg offset 0x%x, ret %d\n", + phy_sus_reg->offset, ret); mutex_unlock(&rport->mutex); - rockchip_usb2phy_power_off(rport->phy); - mutex_lock(&rport->mutex); + return; } - /* put the controller in non-driving mode */ - property_enable(base, &rphy->phy_cfg->chg_det.opmode, false); + + /* Set the PHY in charger detection mode */ + property_enable(base, &rphy->phy_cfg->chg_det.chg_mode, true); /* Start DCD processing stage 1 */ rockchip_chg_enable_dcd(rphy, true); rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD; @@ -1292,8 +1314,17 @@ static void rockchip_chg_detect_work(struct work_struct *work) rphy->chg_state = USB_CHG_STATE_DETECTED; fallthrough; case USB_CHG_STATE_DETECTED: - /* put the controller in normal mode */ - property_enable(base, &rphy->phy_cfg->chg_det.opmode, true); + /* Restore the PHY suspend configuration */ + phy_sus_reg = &rport->port_cfg->phy_sus; + mask = GENMASK(phy_sus_reg->bitend, phy_sus_reg->bitstart); + ret = regmap_write(base, phy_sus_reg->offset, + ((rphy->phy_sus_cfg << + phy_sus_reg->bitstart) | + (mask << BIT_WRITEABLE_SHIFT))); + if (ret) + dev_err(&rport->phy->dev, + "Fail to set phy_sus reg offset 0x%x, ret %d\n", + phy_sus_reg->offset, ret); mutex_unlock(&rport->mutex); rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work); dev_dbg(&rport->phy->dev, "charger = %s\n", @@ -2455,7 +2486,7 @@ static const struct rockchip_usb2phy_cfg rk1808_phy_cfgs[] = { } }, .chg_det = { - .opmode = { 0x0100, 3, 0, 5, 1 }, + .chg_mode = { 0x0100, 8, 0, 0, 0x1d7 }, .cp_det = { 0x0120, 24, 24, 0, 1 }, .dcp_det = { 0x0120, 23, 23, 0, 1 }, .dp_det = { 0x0120, 25, 25, 0, 1 }, @@ -2507,7 +2538,7 @@ static const struct rockchip_usb2phy_cfg rk312x_phy_cfgs[] = { } }, .chg_det = { - .opmode = { 0x017c, 3, 0, 5, 1 }, + .chg_mode = { 0x017c, 8, 0, 0, 0x1d7 }, .cp_det = { 0x02c0, 6, 6, 0, 1 }, .dcp_det = { 0x02c0, 5, 5, 0, 1 }, .dp_det = { 0x02c0, 7, 7, 0, 1 }, @@ -2558,7 +2589,7 @@ static const struct rockchip_usb2phy_cfg rk3228_phy_cfgs[] = { } }, .chg_det = { - .opmode = { 0x0760, 3, 0, 5, 1 }, + .chg_mode = { 0x0760, 8, 0, 0, 0x1d7 }, .cp_det = { 0x0884, 4, 4, 0, 1 }, .dcp_det = { 0x0884, 3, 3, 0, 1 }, .dp_det = { 0x0884, 5, 5, 0, 1 }, @@ -2631,7 +2662,7 @@ static const struct rockchip_usb2phy_cfg rk3308_phy_cfgs[] = { } }, .chg_det = { - .opmode = { 0x0100, 3, 0, 5, 1 }, + .chg_mode = { 0x0100, 8, 0, 0, 0x1d7 }, .cp_det = { 0x0120, 24, 24, 0, 1 }, .dcp_det = { 0x0120, 23, 23, 0, 1 }, .dp_det = { 0x0120, 25, 25, 0, 1 }, @@ -2688,7 +2719,7 @@ static const struct rockchip_usb2phy_cfg rk3328_phy_cfgs[] = { } }, .chg_det = { - .opmode = { 0x0100, 3, 0, 5, 1 }, + .chg_mode = { 0x0100, 8, 0, 0, 0x1d7 }, .cp_det = { 0x0120, 24, 24, 0, 1 }, .dcp_det = { 0x0120, 23, 23, 0, 1 }, .dp_det = { 0x0120, 25, 25, 0, 1 }, @@ -2758,7 +2789,7 @@ static const struct rockchip_usb2phy_cfg rk3368_phy_cfgs[] = { } }, .chg_det = { - .opmode = { 0x0700, 3, 0, 5, 1 }, + .chg_mode = { 0x0700, 8, 0, 0, 0x1d7 }, .cp_det = { 0x04b8, 30, 30, 0, 1 }, .dcp_det = { 0x04b8, 29, 29, 0, 1 }, .dp_det = { 0x04b8, 31, 31, 0, 1 }, @@ -2814,7 +2845,7 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = { } }, .chg_det = { - .opmode = { 0xe454, 3, 0, 5, 1 }, + .chg_mode = { 0xe454, 8, 0, 0, 0x1d7 }, .cp_det = { 0xe2ac, 2, 2, 0, 1 }, .dcp_det = { 0xe2ac, 1, 1, 0, 1 }, .dp_det = { 0xe2ac, 0, 0, 0, 1 }, @@ -2864,7 +2895,7 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = { } }, .chg_det = { - .opmode = { 0xe464, 3, 0, 5, 1 }, + .chg_mode = { 0xe464, 8, 0, 0, 0x1d7 }, .cp_det = { 0xe2ac, 5, 5, 0, 1 }, .dcp_det = { 0xe2ac, 4, 4, 0, 1 }, .dp_det = { 0xe2ac, 3, 3, 0, 1 }, @@ -2922,7 +2953,7 @@ static const struct rockchip_usb2phy_cfg rk3568_phy_cfgs[] = { } }, .chg_det = { - .opmode = { 0x0000, 3, 0, 5, 1 }, + .chg_mode = { 0x0000, 8, 0, 0, 0x1d7 }, .cp_det = { 0x00c0, 24, 24, 0, 1 }, .dcp_det = { 0x00c0, 23, 23, 0, 1 }, .dp_det = { 0x00c0, 25, 25, 0, 1 }, @@ -2988,7 +3019,7 @@ static const struct rockchip_usb2phy_cfg rv1108_phy_cfgs[] = { } }, .chg_det = { - .opmode = { 0x0100, 3, 0, 5, 1 }, + .chg_mode = { 0x0100, 8, 0, 0, 0x1d7 }, .cp_det = { 0x0804, 1, 1, 0, 1 }, .dcp_det = { 0x0804, 0, 0, 0, 1 }, .dp_det = { 0x0804, 2, 2, 0, 1 },