mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
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: Hans de Goede <hdegoede@redhat.com> Acked-by: Kishon Vijay Abraham I <kishon@ti.com> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
This commit is contained in:
parent
956bc8696e
commit
91d96f06a7
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user