From f7486395641e110be2968f68db4a437cb008345e Mon Sep 17 00:00:00 2001 From: William Wu Date: Tue, 8 Dec 2020 11:05:55 +0800 Subject: [PATCH] phy: rockchip: inno-usb2: fix force mode for rk3568 otg This patch adds a new vbus_detect helper function to control the vbus voltage level detection for rk3568 otg port. And fix the issue that the bvalid irq status and id irq status are not handled in the rockchip_usb2phy_irq() for otg host mode when force mode via the sys interface "otg_mode". Change-Id: I75a102034e8dd3ad47de67da4e5120e28564368e Signed-off-by: William Wu Signed-off-by: Frank Wang --- drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 51 +++++++++++++++++-- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index 516187562d3e..b4b655d6caa8 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -185,6 +185,7 @@ struct rockchip_usb2phy_port_cfg { * @reg: the address offset of grf for usb-phy config. * @num_ports: specify how many ports that the phy has. * @phy_tuning: phy default parameters tuning. + * @vbus_detect: vbus voltage level detection function. * @clkout_ctl: keep on/turn off output clk of phy. * @port_cfgs: usb-phy port configurations. * @chg_det: charger detection registers. @@ -193,6 +194,7 @@ struct rockchip_usb2phy_cfg { unsigned int reg; unsigned int num_ports; int (*phy_tuning)(struct rockchip_usb2phy *rphy); + int (*vbus_detect)(struct rockchip_usb2phy *rphy, bool en); struct usb2phy_reg clkout_ctl; const struct rockchip_usb2phy_port_cfg port_cfgs[USB2PHY_NUM_PORTS]; const struct rockchip_chg_det_reg chg_det; @@ -839,7 +841,11 @@ static int rockchip_usb2phy_set_mode(struct phy *phy, return ret; } - ret = property_enable(rphy->grf, &rport->port_cfg->vbus_det_en, vbus_det_en); + if (rphy->phy_cfg->vbus_detect) + rphy->phy_cfg->vbus_detect(rphy, vbus_det_en); + else + ret = property_enable(rphy->grf, &rport->port_cfg->vbus_det_en, + vbus_det_en); return ret; } @@ -1496,7 +1502,6 @@ static irqreturn_t rockchip_usb2phy_id_irq(int irq, void *data) cable_vbus_state = false; } - extcon_set_state(rphy->edev, EXTCON_USB_HOST, cable_vbus_state); extcon_set_state(rphy->edev, EXTCON_USB_VBUS_EN, cable_vbus_state); @@ -1527,17 +1532,37 @@ static irqreturn_t rockchip_usb2phy_irq(int irq, void *data) struct rockchip_usb2phy_port *rport; irqreturn_t ret = IRQ_NONE; unsigned int index; + bool force_mode; for (index = 0; index < rphy->phy_cfg->num_ports; index++) { rport = &rphy->ports[index]; if (!rport->phy) continue; + /* Handle linestate irq for both otg port and host port */ ret = rockchip_usb2phy_linestate_irq(irq, rport); + /* + * Handle bvalid irq and id irq for otg port which + * is assigned to otg controller. + */ if (rport->port_id == USB2PHY_PORT_OTG && - (rport->mode == USB_DR_MODE_PERIPHERAL || - rport->mode == USB_DR_MODE_OTG)) { + rport->mode != USB_DR_MODE_UNKNOWN) { + if (rport->mode == USB_DR_MODE_HOST) { + /* + * If otg port work as usb host mode and + * force_mode is true, it means that the + * otg port is forced to host mode by the + * grf plug iddig indicator via the sys + * interface "otg_mode". We need to handle + * the bvalid irq and id irq in this case. + */ + force_mode = property_enabled(rphy->grf, + &rport->port_cfg->iddig_en); + if (!force_mode) + continue; + } + if (!rport->vbus_always_on) ret |= rockchip_usb2phy_bvalid_irq(irq, rport); @@ -2241,6 +2266,23 @@ static int rk3568_usb2phy_tuning(struct rockchip_usb2phy *rphy) return ret; } +static int rk3568_vbus_detect_control(struct rockchip_usb2phy *rphy, bool en) +{ + u32 reg; + + if (en) { + reg = readl(rphy->phy_base + 0x3c); + /* Enable vbus voltage level detection function */ + writel(reg & ~BIT(7), rphy->phy_base + 0x3c); + } else { + reg = readl(rphy->phy_base + 0x3c); + /* Disable vbus voltage level detection function */ + writel(reg | BIT(7), rphy->phy_base + 0x3c); + } + + return 0; +} + #ifdef CONFIG_PM_SLEEP static int rockchip_usb2phy_pm_suspend(struct device *dev) { @@ -2839,6 +2881,7 @@ static const struct rockchip_usb2phy_cfg rk3568_phy_cfgs[] = { .reg = 0xfe8a0000, .num_ports = 2, .phy_tuning = rk3568_usb2phy_tuning, + .vbus_detect = rk3568_vbus_detect_control, .clkout_ctl = { 0x0008, 4, 4, 1, 0 }, .port_cfgs = { [USB2PHY_PORT_OTG] = {