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@crapouillou.net> Signed-off-by: Bin Liu <b-liu@ti.com> Link: https://lore.kernel.org/r/20200316211136.2274-5-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
57aadb46bd
commit
5004eaa28e
@ -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"
|
||||
|
@ -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,40 @@ 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 usb_role_switch *sw,
|
||||
enum usb_role role)
|
||||
{
|
||||
struct jz4740_glue *glue = usb_role_switch_get_drvdata(sw);
|
||||
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,
|
||||
.driver_data = glue,
|
||||
.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 +120,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 +137,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,
|
||||
|
Loading…
Reference in New Issue
Block a user