提交 91d96f06 编写于 作者: H Hans de Goede 提交者: Kishon Vijay Abraham I

phy-sun4i-usb: Add workaround for missing Vbus det interrupts on A31

The A31 companion pmic (axp221) does not generate vbus change interrupts
when the board is driving vbus, so we must poll when using the pmic for
vbus-det _and_ we're driving vbus.
Signed-off-by: NHans de Goede <hdegoede@redhat.com>
Acked-by: NKishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: NKishon Vijay Abraham I <kishon@ti.com>
上级 956bc869
......@@ -94,6 +94,7 @@
enum sun4i_usb_phy_type {
sun4i_a10_phy,
sun6i_a31_phy,
sun8i_a33_phy,
sun8i_h3_phy,
};
......@@ -122,7 +123,6 @@ struct sun4i_usb_phy_data {
/* phy0 / otg related variables */
struct extcon_dev *extcon;
bool phy0_init;
bool phy0_poll;
struct gpio_desc *id_det_gpio;
struct gpio_desc *vbus_det_gpio;
struct power_supply *vbus_power_supply;
......@@ -343,6 +343,24 @@ static bool sun4i_usb_phy0_have_vbus_det(struct sun4i_usb_phy_data *data)
return data->vbus_det_gpio || data->vbus_power_supply;
}
static bool sun4i_usb_phy0_poll(struct sun4i_usb_phy_data *data)
{
if ((data->id_det_gpio && data->id_det_irq <= 0) ||
(data->vbus_det_gpio && data->vbus_det_irq <= 0))
return true;
/*
* The A31 companion pmic (axp221) does not generate vbus change
* interrupts when the board is driving vbus, so we must poll
* when using the pmic for vbus-det _and_ we're driving vbus.
*/
if (data->cfg->type == sun6i_a31_phy &&
data->vbus_power_supply && data->phys[0].regulator_on)
return true;
return false;
}
static int sun4i_usb_phy_power_on(struct phy *_phy)
{
struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
......@@ -364,7 +382,7 @@ static int sun4i_usb_phy_power_on(struct phy *_phy)
phy->regulator_on = true;
/* We must report Vbus high within OTG_TIME_A_WAIT_VRISE msec. */
if (phy->index == 0 && data->vbus_det_gpio && data->phy0_poll)
if (phy->index == 0 && sun4i_usb_phy0_poll(data))
mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
return 0;
......@@ -385,7 +403,7 @@ static int sun4i_usb_phy_power_off(struct phy *_phy)
* phy0 vbus typically slowly discharges, sometimes this causes the
* Vbus gpio to not trigger an edge irq on Vbus off, so force a rescan.
*/
if (phy->index == 0 && data->vbus_det_gpio && !data->phy0_poll)
if (phy->index == 0 && !sun4i_usb_phy0_poll(data))
mod_delayed_work(system_wq, &data->detect, POLL_TIME);
return 0;
......@@ -468,7 +486,7 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
if (vbus_notify)
extcon_set_cable_state_(data->extcon, EXTCON_USB, vbus_det);
if (data->phy0_poll)
if (sun4i_usb_phy0_poll(data))
queue_delayed_work(system_wq, &data->detect, POLL_TIME);
}
......@@ -644,11 +662,6 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
}
data->id_det_irq = gpiod_to_irq(data->id_det_gpio);
data->vbus_det_irq = gpiod_to_irq(data->vbus_det_gpio);
if ((data->id_det_gpio && data->id_det_irq <= 0) ||
(data->vbus_det_gpio && data->vbus_det_irq <= 0))
data->phy0_poll = true;
if (data->id_det_irq > 0) {
ret = devm_request_irq(dev, data->id_det_irq,
sun4i_usb_phy0_id_vbus_det_irq,
......@@ -660,6 +673,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
}
}
data->vbus_det_irq = gpiod_to_irq(data->vbus_det_gpio);
if (data->vbus_det_irq > 0) {
ret = devm_request_irq(dev, data->vbus_det_irq,
sun4i_usb_phy0_id_vbus_det_irq,
......@@ -711,7 +725,7 @@ static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = {
static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = {
.num_phys = 3,
.type = sun4i_a10_phy,
.type = sun6i_a31_phy,
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A10,
.dedicated_clocks = true,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册