[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20200115220008.91445-4-paul@crapouillou.net>
Date: Wed, 15 Jan 2020 19:00:06 -0300
From: Paul Cercueil <paul@...pouillou.net>
To: Bin Liu <b-liu@...com>,
Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
Rob Herring <robh+dt@...nel.org>,
Mark Rutland <mark.rutland@....com>
Cc: od@...c.me, linux-usb@...r.kernel.org, devicetree@...r.kernel.org,
linux-kernel@...r.kernel.org, Paul Cercueil <paul@...pouillou.net>
Subject: [PATCH 3/5] usb: musb: jz4740: Register USB role switch
Register a USB role switch, in order to get notified by the connector
driver when the USB role changes. The notification is then transmitted
to the PHY.
Signed-off-by: Paul Cercueil <paul@...pouillou.net>
---
drivers/usb/musb/Kconfig | 1 +
drivers/usb/musb/jz4740.c | 46 +++++++++++++++++++++++++++++++++++++++
2 files changed, 47 insertions(+)
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index c4b349e074c1..3268adb7d7cf 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -113,6 +113,7 @@ config USB_MUSB_JZ4740
depends on MIPS || COMPILE_TEST
depends on USB_MUSB_GADGET
depends on USB=n || USB_OTG_BLACKLIST_HUB
+ select USB_ROLE_SWITCH
config USB_MUSB_MEDIATEK
tristate "MediaTek platforms"
diff --git a/drivers/usb/musb/jz4740.c b/drivers/usb/musb/jz4740.c
index aa32b5af0c1f..bbfeb9881788 100644
--- a/drivers/usb/musb/jz4740.c
+++ b/drivers/usb/musb/jz4740.c
@@ -12,13 +12,16 @@
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/usb/role.h>
#include <linux/usb/usb_phy_generic.h>
#include "musb_core.h"
struct jz4740_glue {
struct platform_device *pdev;
+ struct musb *musb;
struct clk *clk;
+ struct usb_role_switch *role_sw;
};
static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci)
@@ -72,11 +75,38 @@ static const struct musb_hdrc_config jz4740_musb_config = {
.fifo_cfg_size = ARRAY_SIZE(jz4740_musb_fifo_cfg),
};
+static int jz4740_musb_role_switch_set(struct device *dev, enum usb_role role)
+{
+ struct jz4740_glue *glue = dev_get_drvdata(dev);
+ struct usb_phy *phy = glue->musb->xceiv;
+
+ switch (role) {
+ case USB_ROLE_NONE:
+ atomic_notifier_call_chain(&phy->notifier, USB_EVENT_NONE, phy);
+ break;
+ case USB_ROLE_DEVICE:
+ atomic_notifier_call_chain(&phy->notifier, USB_EVENT_VBUS, phy);
+ break;
+ case USB_ROLE_HOST:
+ atomic_notifier_call_chain(&phy->notifier, USB_EVENT_ID, phy);
+ break;
+ }
+
+ return 0;
+}
+
static int jz4740_musb_init(struct musb *musb)
{
struct device *dev = musb->controller->parent;
+ struct jz4740_glue *glue = dev_get_drvdata(dev);
+ struct usb_role_switch_desc role_sw_desc = {
+ .set = jz4740_musb_role_switch_set,
+ .fwnode = dev_fwnode(dev),
+ };
int err;
+ glue->musb = musb;
+
if (dev->of_node)
musb->xceiv = devm_usb_get_phy_by_phandle(dev, "phys", 0);
else
@@ -88,6 +118,12 @@ static int jz4740_musb_init(struct musb *musb)
return err;
}
+ glue->role_sw = usb_role_switch_register(dev, &role_sw_desc);
+ if (IS_ERR(glue->role_sw)) {
+ dev_err(dev, "Failed to register USB role switch");
+ return PTR_ERR(glue->role_sw);
+ }
+
/*
* Silicon does not implement ConfigData register.
* Set dyn_fifo to avoid reading EP config from hardware.
@@ -99,10 +135,20 @@ static int jz4740_musb_init(struct musb *musb)
return 0;
}
+static int jz4740_musb_exit(struct musb *musb)
+{
+ struct jz4740_glue *glue = dev_get_drvdata(musb->controller->parent);
+
+ usb_role_switch_unregister(glue->role_sw);
+
+ return 0;
+}
+
static const struct musb_platform_ops jz4740_musb_ops = {
.quirks = MUSB_DMA_INVENTRA | MUSB_INDEXED_EP,
.fifo_mode = 2,
.init = jz4740_musb_init,
+ .exit = jz4740_musb_exit,
#ifdef CONFIG_USB_INVENTRA_DMA
.dma_init = musbhs_dma_controller_create_noirq,
.dma_exit = musbhs_dma_controller_destroy,
--
2.24.1
Powered by blists - more mailing lists