|
@@ -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,
|