Skip to content

Commit

Permalink
usb: dwc3: meson-g12a: Add support for IRQ based OTG switching
Browse files Browse the repository at this point in the history
Add support for the OTG ID change interrupt to switch between Host
and Device mode.

Tested on the Hardkernel Odroid-N2 board.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
  • Loading branch information
superna9999 authored and Felipe Balbi committed Jun 18, 2019
1 parent 23c4680 commit f90db10
Showing 1 changed file with 31 additions and 5 deletions.
36 changes: 31 additions & 5 deletions drivers/usb/dwc3/dwc3-meson-g12a.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@
* - Control registers for each USB2 Ports
* - Control registers for the USB PHY layer
* - SuperSpeed PHY can be enabled only if port is used
*
* TOFIX:
* - Add dynamic OTG switching with ID change interrupt
* - Dynamic OTG switching with ID change interrupt
*/

#include <linux/module.h>
Expand Down Expand Up @@ -348,6 +346,22 @@ static enum usb_role dwc3_meson_g12a_role_get(struct device *dev)
USB_ROLE_HOST : USB_ROLE_DEVICE;
}

static irqreturn_t dwc3_meson_g12a_irq_thread(int irq, void *data)
{
struct dwc3_meson_g12a *priv = data;
enum phy_mode otg_id;

otg_id = dwc3_meson_g12a_get_id(priv);
if (otg_id != priv->otg_phy_mode) {
if (dwc3_meson_g12a_otg_mode_set(priv, otg_id))
dev_warn(priv->dev, "Failed to switch OTG mode\n");
}

regmap_update_bits(priv->regmap, USB_R5, USB_R5_ID_DIG_IRQ, 0);

return IRQ_HANDLED;
}

static struct device *dwc3_meson_g12_find_child(struct device *dev,
const char *compatible)
{
Expand All @@ -374,7 +388,7 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev)
void __iomem *base;
struct resource *res;
enum phy_mode otg_id;
int ret, i;
int ret, i, irq;

priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
Expand Down Expand Up @@ -436,6 +450,19 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev)
/* Get dr_mode */
priv->otg_mode = usb_get_dr_mode(dev);

if (priv->otg_mode == USB_DR_MODE_OTG) {
/* Ack irq before registering */
regmap_update_bits(priv->regmap, USB_R5,
USB_R5_ID_DIG_IRQ, 0);

irq = platform_get_irq(pdev, 0);
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
dwc3_meson_g12a_irq_thread,
IRQF_ONESHOT, pdev->name, priv);
if (ret)
return ret;
}

dwc3_meson_g12a_usb_init(priv);

/* Init PHYs */
Expand All @@ -460,7 +487,6 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev)

/* Setup OTG mode corresponding to the ID pin */
if (priv->otg_mode == USB_DR_MODE_OTG) {
/* TOFIX Handle ID mode toggling via IRQ */
otg_id = dwc3_meson_g12a_get_id(priv);
if (otg_id != priv->otg_phy_mode) {
if (dwc3_meson_g12a_otg_mode_set(priv, otg_id))
Expand Down

0 comments on commit f90db10

Please sign in to comment.