phy: rockchip-inno-usb2: use fixed-regulator for vbus power

This patch uses a fixed-regulator instead of GPIO pin for
usb vbus power. It doesn't fix any issue, but it makes more
sense to convert the GPIO code into a fixed-regulator.

Change-Id: I7196a9cd592dbb3fab3ef8b9e99babc613a42869
Signed-off-by: William Wu <william.wu@rock-chips.com>
Signed-off-by: Frank Wang <frank.wang@rock-chips.com>
This commit is contained in:
William Wu
2018-02-24 16:29:32 +08:00
committed by Tao Huang
parent 389dfa9d6c
commit 46df64378a
2 changed files with 98 additions and 10 deletions

View File

@@ -115,6 +115,10 @@ properties:
Phandle to a regulator that provides power to VBUS.
See ./phy-bindings.txt for details.
vbus-supply:
description:
Phandle to a fixed-regulator that provides power to VBUS.
rockchip,utmi-bypass-uart:
$ref: /schemas/types.yaml#/definitions/flag
description: when set, indicates that support usb to bypass uart

View File

@@ -198,6 +198,7 @@ struct rockchip_usb2phy_cfg {
* false - use bvalid to get vbus status
* @vbus_attached: otg device vbus status.
* @vbus_always_on: otg vbus is always powered on.
* @vbus_enabled: vbus regulator status.
* @bypass_uart_en: usb bypass uart enable, passed from DT.
* @bvalid_irq: IRQ number assigned for vbus valid rise detection.
* @ls_irq: IRQ number assigned for linestate detection.
@@ -209,6 +210,7 @@ struct rockchip_usb2phy_cfg {
* @bypass_uart_work: usb bypass uart work.
* @otg_sm_work: OTG state machine work.
* @sm_work: HOST state machine work.
* @vbus: vbus regulator supply on few rockchip boards.
* @port_cfg: port register configuration, assigned by driver data.
* @event_nb: hold event notification callback.
* @state: define OTG enumeration states before device reset.
@@ -222,6 +224,7 @@ struct rockchip_usb2phy_port {
bool utmi_avalid;
bool vbus_attached;
bool vbus_always_on;
bool vbus_enabled;
bool bypass_uart_en;
int bvalid_irq;
int ls_irq;
@@ -232,6 +235,7 @@ struct rockchip_usb2phy_port {
struct delayed_work chg_work;
struct delayed_work otg_sm_work;
struct delayed_work sm_work;
struct regulator *vbus;
const struct rockchip_usb2phy_port_cfg *port_cfg;
struct notifier_block event_nb;
enum usb_otg_state state;
@@ -742,6 +746,29 @@ static int rockchip_usb2phy_exit(struct phy *phy)
return 0;
}
static int rockchip_set_vbus_power(struct rockchip_usb2phy_port *rport,
bool en)
{
int ret = 0;
if (!rport->vbus)
return 0;
if (en && !rport->vbus_enabled) {
ret = regulator_enable(rport->vbus);
if (ret)
dev_err(&rport->phy->dev,
"Failed to enable VBUS supply\n");
} else if (!en && rport->vbus_enabled) {
ret = regulator_disable(rport->vbus);
}
if (ret == 0)
rport->vbus_enabled = en;
return ret;
}
static int rockchip_usb2phy_set_mode(struct phy *phy,
enum phy_mode mode, int submode)
{
@@ -761,9 +788,21 @@ static int rockchip_usb2phy_set_mode(struct phy *phy,
*/
fallthrough;
case PHY_MODE_USB_DEVICE:
/* Disable VBUS supply */
rockchip_set_vbus_power(rport, false);
extcon_set_state_sync(rphy->edev, EXTCON_USB_VBUS_EN, false);
vbus_det_en = true;
break;
case PHY_MODE_USB_HOST:
/* Enable VBUS supply */
ret = rockchip_set_vbus_power(rport, true);
if (ret) {
dev_err(&rport->phy->dev,
"Failed to set host mode\n");
return ret;
}
extcon_set_state_sync(rphy->edev, EXTCON_USB_VBUS_EN, true);
fallthrough;
case PHY_MODE_INVALID:
vbus_det_en = false;
@@ -1419,6 +1458,7 @@ static irqreturn_t rockchip_usb2phy_id_irq(int irq, void *data)
{
struct rockchip_usb2phy_port *rport = data;
struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
bool cable_vbus_state = false;
if (!property_enabled(rphy->grf, &rport->port_cfg->idfall_det_st) &&
!property_enabled(rphy->grf, &rport->port_cfg->idrise_det_st))
@@ -1430,18 +1470,22 @@ static irqreturn_t rockchip_usb2phy_id_irq(int irq, void *data)
if (property_enabled(rphy->grf, &rport->port_cfg->idfall_det_st)) {
property_enable(rphy->grf, &rport->port_cfg->idfall_det_clr,
true);
extcon_set_state(rphy->edev, EXTCON_USB_HOST, true);
extcon_set_state(rphy->edev, EXTCON_USB_VBUS_EN, true);
cable_vbus_state = true;
} else if (property_enabled(rphy->grf, &rport->port_cfg->idrise_det_st)) {
property_enable(rphy->grf, &rport->port_cfg->idrise_det_clr,
true);
extcon_set_state(rphy->edev, EXTCON_USB_HOST, false);
extcon_set_state(rphy->edev, EXTCON_USB_VBUS_EN, false);
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);
extcon_sync(rphy->edev, EXTCON_USB_HOST);
extcon_sync(rphy->edev, EXTCON_USB_VBUS_EN);
rockchip_set_vbus_power(rport, cable_vbus_state);
mutex_unlock(&rport->mutex);
return IRQ_HANDLED;
@@ -1511,6 +1555,7 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_OTG];
rport->state = OTG_STATE_UNDEFINED;
rport->vbus_attached = false;
rport->vbus_enabled = false;
rport->perip_connected = false;
mutex_init(&rport->mutex);
@@ -1523,14 +1568,35 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
rport->utmi_avalid =
of_property_read_bool(child_np, "rockchip,utmi-avalid");
/* Get Vbus regulators */
rport->vbus = devm_regulator_get_optional(&rport->phy->dev, "vbus");
if (IS_ERR(rport->vbus)) {
ret = PTR_ERR(rport->vbus);
if (ret == -EPROBE_DEFER)
return ret;
dev_warn(&rport->phy->dev, "Failed to get VBUS supply regulator\n");
rport->vbus = NULL;
}
rport->mode = of_usb_get_dr_mode_by_phy(child_np, -1);
if (rport->mode == USB_DR_MODE_HOST ||
rport->mode == USB_DR_MODE_UNKNOWN ||
rport->vbus_always_on) {
ret = 0;
rport->mode == USB_DR_MODE_UNKNOWN) {
if (rphy->edev_self) {
extcon_set_state(rphy->edev, EXTCON_USB, false);
extcon_set_state(rphy->edev, EXTCON_USB_HOST, true);
/* Enable VBUS supply */
extcon_set_state(rphy->edev, EXTCON_USB_VBUS_EN, true);
ret = rockchip_set_vbus_power(rport, true);
if (ret)
return ret;
}
goto out;
}
if (rport->vbus_always_on)
goto out;
INIT_DELAYED_WORK(&rport->bypass_uart_work,
rockchip_usb_bypass_uart_work);
INIT_DELAYED_WORK(&rport->chg_work, rockchip_chg_detect_work);
@@ -1610,9 +1676,10 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
extcon_set_state(rphy->edev, EXTCON_USB, false);
extcon_set_state(rphy->edev, EXTCON_USB_HOST, true);
extcon_set_state(rphy->edev, EXTCON_USB_VBUS_EN, true);
} else {
extcon_set_state(rphy->edev, EXTCON_USB_HOST, false);
extcon_set_state(rphy->edev, EXTCON_USB_VBUS_EN, false);
/* Enable VBUS supply */
ret = rockchip_set_vbus_power(rport, true);
if (ret)
return ret;
}
}
@@ -1967,6 +2034,23 @@ static int rockchip_usb2phy_pm_resume(struct device *dev)
"failed to enable id irq\n");
return ret;
}
if (!property_enabled(rphy->grf,
&rport->port_cfg->utmi_iddig) &&
!extcon_get_state(rphy->edev, EXTCON_USB_HOST)) {
dev_dbg(&rport->phy->dev,
"port power on when resume\n");
extcon_set_state_sync(rphy->edev,
EXTCON_USB_HOST,
true);
/* Enable VBUS supply */
extcon_set_state_sync(rphy->edev,
EXTCON_USB_VBUS_EN,
true);
ret = rockchip_set_vbus_power(rport, true);
if (ret)
return ret;
}
}
}