mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 11:50:43 +09:00
phy: rockchip: inno-usb2: keep utmi clk on during charge detection
The utmi clk is provided by the USB PHY for the USB controller. And the utmi clk is disabled if the USB PHY enter suspend mode. The current charge detection sets the USB PHY in suspend mode at first, then take about hundreds of milliseconds to do charge detection, in other words, the utmi clk will be disabled hundreds of milliseconds. It may cause the USB controller work abnormally during the charge detection. Actually, the conditions for charger detection is: 1. Set the utmi_opmode in non-driving mode. 2. Set the utmi_xcvrselect to FS speed. 3. Set the utmi_termselect to FS speed. 4. Enable the DP/DM pulldown resistor. This patch adds a new chg_mode to set the PHY in charge detection mode according to the above conditions, and set the PHY in normal mode to keep the utmi clk at the same time. Signed-off-by: William Wu <william.wu@rock-chips.com> Change-Id: I1cbf565d5145bdae5bc91132bc5fbff23a5cc443
This commit is contained in:
@@ -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 },
|
||||
|
||||
Reference in New Issue
Block a user