From 9f101a73b085efbd1f6708f51a57f56fdd46a11b Mon Sep 17 00:00:00 2001 From: Saurav Girepunje Date: Wed, 15 Jan 2020 07:25:23 -0600 Subject: usb: musb: core: Update the function description Update the function description of musb_stage0_irq() to remove unused parameter. Signed-off-by: Saurav Girepunje [b-liu@ti.com: revised commit log] Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-2-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 5ebf30bd61bd..48d95850152d 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -909,7 +909,6 @@ static void musb_handle_intr_reset(struct musb *musb) * @param musb instance pointer * @param int_usb register contents * @param devctl - * @param power */ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, -- cgit v1.2.3-59-g8ed1b From 908f6fc3a14050961210f9754855f9e0eccb6d46 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Wed, 15 Jan 2020 07:25:24 -0600 Subject: usb: musb: sunxi: propagate devicetree node to glue pdev In order for devicetree nodes to be correctly associated with attached devices, the controller node needs to be propagated to the glue device. Signed-off-by: Mans Rullgard Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-3-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/sunxi.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c index 832a41f9ee7d..a72665fbf111 100644 --- a/drivers/usb/musb/sunxi.c +++ b/drivers/usb/musb/sunxi.c @@ -781,6 +781,8 @@ static int sunxi_musb_probe(struct platform_device *pdev) pinfo.name = "musb-hdrc"; pinfo.id = PLATFORM_DEVID_AUTO; pinfo.parent = &pdev->dev; + pinfo.fwnode = of_fwnode_handle(pdev->dev.of_node); + pinfo.of_node_reused = true; pinfo.res = pdev->resource; pinfo.num_res = pdev->num_resources; pinfo.data = &pdata; -- cgit v1.2.3-59-g8ed1b From 1b569569a955c53b00a04d86cd84e60efe4c14be Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Wed, 15 Jan 2020 07:25:25 -0600 Subject: usb: musb: jz4740: Drop dependency on NOP_USB_XCEIV The driver does not depend directly on the NOP transceiver. It can compile and work just fine without it. Signed-off-by: Paul Cercueil Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-4-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 52f8e2b57ad5..4678ebc889b5 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -111,7 +111,6 @@ config USB_MUSB_UX500 config USB_MUSB_JZ4740 tristate "JZ4740" - depends on NOP_USB_XCEIV depends on MIPS || COMPILE_TEST depends on USB_MUSB_GADGET depends on USB=n || USB_OTG_BLACKLIST_HUB -- cgit v1.2.3-59-g8ed1b From 91b6dec32e5c25fbdbb564d1e5af23764ec17ef1 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 15 Jan 2020 07:25:26 -0600 Subject: usb: musb: omap2430: Get rid of musb .set_vbus for omap2430 glue We currently have musb_set_vbus() called from two different paths. Mostly it gets called from the USB PHY via omap_musb_set_mailbox(), but in some cases it can get also called from musb_stage0_irq() rather via .set_vbus: (musb_set_host [musb_hdrc]) (omap2430_musb_set_vbus [omap2430]) (musb_stage0_irq [musb_hdrc]) (musb_interrupt [musb_hdrc]) (omap2430_musb_interrupt [omap2430]) This is racy and will not work with introducing generic helper functions for musb_set_host() and musb_set_peripheral(). We want to get rid of the busy loops in favor of usleep_range(). Let's just get rid of .set_vbus for omap2430 glue layer and let the PHY code handle VBUS with musb_set_vbus(). Note that in the follow-up patch we can completely remove omap2430_musb_set_vbus(), but let's do it in a separate patch as this change may actually turn out to be needed as a fix. Reported-by: Pavel Machek Acked-by: Pavel Machek Signed-off-by: Tony Lindgren Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-5-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/omap2430.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index a3d2fef67746..5c93226e0e20 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -361,8 +361,6 @@ static const struct musb_platform_ops omap2430_ops = { .init = omap2430_musb_init, .exit = omap2430_musb_exit, - .set_vbus = omap2430_musb_set_vbus, - .enable = omap2430_musb_enable, .disable = omap2430_musb_disable, -- cgit v1.2.3-59-g8ed1b From ce3ab6503ebaba976405858616d7f6094e364973 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 15 Jan 2020 07:25:27 -0600 Subject: usb: musb: omap2430: Wait on enable to avoid babble We can get babble interrupt if we attempt to switch to USB host mode too soon after enabling musb. Let's fix the issue by waiting a bit in runtime_resume. Cc: Jacopo Mondi Cc: Marcel Partap Cc: Merlijn Wajer Cc: Michael Scott Cc: NeKit Cc: Pavel Machek Cc: Sebastian Reichel Acked-by: Pavel Machek Signed-off-by: Tony Lindgren Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-6-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/omap2430.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 5c93226e0e20..920862c3fc64 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -550,6 +550,9 @@ static int omap2430_runtime_resume(struct device *dev) musb_writel(musb->mregs, OTG_INTERFSEL, musb->context.otg_interfsel); + /* Wait for musb to get oriented. Otherwise we can get babble */ + usleep_range(200000, 250000); + return 0; } -- cgit v1.2.3-59-g8ed1b From 15f1122f92c02f654037d8fb98164b785207b7af Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 15 Jan 2020 07:25:28 -0600 Subject: usb: musb: omap2430: Handle multiple ID ground interrupts We currently get "unhandled DISCONNECT transition" warnings from musb core on device disconnect as things are wrongly set to OTG_STATE_A_IDLE in host mode when enumerating devices. We can also get "Failed to write reg index" errors after enumerating. This is happening at least with cpcap phy where we get multiple ID ground interrupts. Looks like it's VBUS keeps timing out and needs to be kicked when the phy sends multiple ID ground interrupts during host mode. Cc: Jacopo Mondi Cc: Marcel Partap Cc: Merlijn Wajer Cc: Michael Scott Cc: NeKit Cc: Pavel Machek Cc: Sebastian Reichel Acked-by: Pavel Machek Signed-off-by: Tony Lindgren Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-7-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/omap2430.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 920862c3fc64..e572ee624128 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -151,13 +151,26 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) switch (glue->status) { case MUSB_ID_GROUND: dev_dbg(musb->controller, "ID GND\n"); - - musb->xceiv->otg->state = OTG_STATE_A_IDLE; - musb->xceiv->last_event = USB_EVENT_ID; - if (musb->gadget_driver) { - omap_control_usb_set_mode(glue->control_otghs, - USB_MODE_HOST); + switch (musb->xceiv->otg->state) { + case OTG_STATE_A_WAIT_VRISE: + case OTG_STATE_A_WAIT_BCON: + case OTG_STATE_A_HOST: + case OTG_STATE_A_IDLE: + /* + * On multiple ID ground interrupts just keep enabling + * VBUS. At least cpcap VBUS shuts down otherwise. + */ omap2430_musb_set_vbus(musb, 1); + break; + default: + musb->xceiv->otg->state = OTG_STATE_A_IDLE; + musb->xceiv->last_event = USB_EVENT_ID; + if (musb->gadget_driver) { + omap_control_usb_set_mode(glue->control_otghs, + USB_MODE_HOST); + omap2430_musb_set_vbus(musb, 1); + } + break; } break; -- cgit v1.2.3-59-g8ed1b From 93dc256871297071a24f7f9ce0abfddfff15094d Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 15 Jan 2020 07:25:29 -0600 Subject: usb: musb: Add musb_set_host and peripheral and use them for omap2430 At least some revisions of musb core need to set devctl session bit in peripheral mode to force musb to host mode. And we have places clearing the devctl session bit. Let's add a generic function to do this, and use it for omap2430. This should get us a bit closer to completely removing devctl register tinkering in the SoC glue code. Before making use of this code for the other glue layers, things need to be tested carefully as there may be a approximately a 200 ms delay needed between powering up musb and calling musb_set_host() to avoid. Otherwise the system hangs at least with omap2430 glue layer. Acked-by: Pavel Machek Signed-off-by: Tony Lindgren [b-liu@ti.com: fixed "line over 80 characters" warning] Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-8-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 103 +++++++++++++++++++++++++++++++++++++++++++ drivers/usb/musb/musb_core.h | 3 ++ drivers/usb/musb/omap2430.c | 71 +++++++++-------------------- 3 files changed, 128 insertions(+), 49 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 48d95850152d..34090707d122 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -73,6 +73,7 @@ #include #include #include +#include #include #include #include @@ -414,6 +415,108 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) return hw_ep->musb->io.write_fifo(hw_ep, len, src); } +static u8 musb_read_devctl(struct musb *musb) +{ + return musb_readb(musb->mregs, MUSB_DEVCTL); +} + +/** + * musb_set_host - set and initialize host mode + * @musb: musb controller driver data + * + * At least some musb revisions need to enable devctl session bit in + * peripheral mode to switch to host mode. Initializes things to host + * mode and sets A_IDLE. SoC glue needs to advance state further + * based on phy provided VBUS state. + * + * Note that the SoC glue code may need to wait for musb to settle + * on enable before calling this to avoid babble. + */ +int musb_set_host(struct musb *musb) +{ + int error = 0; + u8 devctl; + + if (!musb) + return -EINVAL; + + devctl = musb_read_devctl(musb); + if (!(devctl & MUSB_DEVCTL_BDEVICE)) { + dev_info(musb->controller, + "%s: already in host mode: %02x\n", + __func__, devctl); + goto init_data; + } + + devctl |= MUSB_DEVCTL_SESSION; + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + + error = readx_poll_timeout(musb_read_devctl, musb, devctl, + !(devctl & MUSB_DEVCTL_BDEVICE), 5000, + 1000000); + if (error) { + dev_err(musb->controller, "%s: could not set host: %02x\n", + __func__, devctl); + + return error; + } + +init_data: + musb->is_active = 1; + musb->xceiv->otg->state = OTG_STATE_A_IDLE; + MUSB_HST_MODE(musb); + + return error; +} +EXPORT_SYMBOL_GPL(musb_set_host); + +/** + * musb_set_peripheral - set and initialize peripheral mode + * @musb: musb controller driver data + * + * Clears devctl session bit and initializes things for peripheral + * mode and sets B_IDLE. SoC glue needs to advance state further + * based on phy provided VBUS state. + */ +int musb_set_peripheral(struct musb *musb) +{ + int error = 0; + u8 devctl; + + if (!musb) + return -EINVAL; + + devctl = musb_read_devctl(musb); + if (devctl & MUSB_DEVCTL_BDEVICE) { + dev_info(musb->controller, + "%s: already in peripheral mode: %02x\n", + __func__, devctl); + + goto init_data; + } + + devctl &= ~MUSB_DEVCTL_SESSION; + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + + error = readx_poll_timeout(musb_read_devctl, musb, devctl, + devctl & MUSB_DEVCTL_BDEVICE, 5000, + 1000000); + if (error) { + dev_err(musb->controller, "%s: could not set periperal: %02x\n", + __func__, devctl); + + return error; + } + +init_data: + musb->is_active = 0; + musb->xceiv->otg->state = OTG_STATE_B_IDLE; + MUSB_DEV_MODE(musb); + + return error; +} +EXPORT_SYMBOL_GPL(musb_set_peripheral); + /*-------------------------------------------------------------------------*/ /* for high speed test mode; see USB 2.0 spec 7.1.20 */ diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 04203b7126d5..8a13a46cd891 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -487,6 +487,9 @@ extern void musb_start(struct musb *musb); extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src); extern void musb_read_fifo(struct musb_hw_ep *ep, u16 len, u8 *dst); +extern int musb_set_host(struct musb *musb); +extern int musb_set_peripheral(struct musb *musb); + extern void musb_load_testpacket(struct musb *); extern irqreturn_t musb_interrupt(struct musb *); diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index e572ee624128..9c1b72a4b12f 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -38,65 +38,38 @@ struct omap2430_glue { static struct omap2430_glue *_glue; +/* + * HDRC controls CPEN, but beware current surges during device connect. + * They can trigger transient overcurrent conditions that must be ignored. + * + * Note that we're skipping A_WAIT_VFALL -> A_IDLE and jumping right to B_IDLE + * as set by musb_set_peripheral(). + */ static void omap2430_musb_set_vbus(struct musb *musb, int is_on) { - struct usb_otg *otg = musb->xceiv->otg; - u8 devctl; - unsigned long timeout = jiffies + msecs_to_jiffies(1000); - /* HDRC controls CPEN, but beware current surges during device - * connect. They can trigger transient overcurrent conditions - * that must be ignored. - */ - - devctl = musb_readb(musb->mregs, MUSB_DEVCTL); + struct usb_otg *otg = musb->xceiv->otg; + int error; if (is_on) { - if (musb->xceiv->otg->state == OTG_STATE_A_IDLE) { - int loops = 100; - /* start the session */ - devctl |= MUSB_DEVCTL_SESSION; - musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); - /* - * Wait for the musb to set as A device to enable the - * VBUS - */ - while (musb_readb(musb->mregs, MUSB_DEVCTL) & - MUSB_DEVCTL_BDEVICE) { - - mdelay(5); - cpu_relax(); - - if (time_after(jiffies, timeout) - || loops-- <= 0) { - dev_err(musb->controller, - "configured as A device timeout"); - break; - } + switch (musb->xceiv->otg->state) { + case OTG_STATE_A_IDLE: + error = musb_set_host(musb); + if (!error) { + musb->xceiv->otg->state = + OTG_STATE_A_WAIT_VRISE; + otg_set_vbus(otg, 1); } - + break; + default: otg_set_vbus(otg, 1); - } else { - musb->is_active = 1; - musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; - devctl |= MUSB_DEVCTL_SESSION; - MUSB_HST_MODE(musb); + break; } } else { - musb->is_active = 0; - - /* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and - * jumping right to B_IDLE... - */ - - musb->xceiv->otg->state = OTG_STATE_B_IDLE; - devctl &= ~MUSB_DEVCTL_SESSION; - - MUSB_DEV_MODE(musb); + error = musb_set_peripheral(musb); + otg_set_vbus(otg, 0); } - musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); - dev_dbg(musb->controller, "VBUS %s, devctl %02x " - /* otg %3x conf %08x prcm %08x */ "\n", + dev_dbg(musb->controller, "VBUS %s, devctl %02x\n", usb_otg_state_string(musb->xceiv->otg->state), musb_readb(musb->mregs, MUSB_DEVCTL)); } -- cgit v1.2.3-59-g8ed1b From b769ae4f26e5892df70bf4d3005fe0db35c8ba7b Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 15 Jan 2020 07:25:30 -0600 Subject: usb: musb: omap2430: Clean up enable and remove devctl tinkering There should be no need to tinker with devctl in enable in the SoC glue code. We have musb_start() to take care of handling it already. Acked-by: Pavel Machek Signed-off-by: Tony Lindgren Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-9-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/omap2430.c | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 9c1b72a4b12f..2cc54135bb8b 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -276,33 +276,13 @@ static int omap2430_musb_init(struct musb *musb) static void omap2430_musb_enable(struct musb *musb) { - u8 devctl; - unsigned long timeout = jiffies + msecs_to_jiffies(1000); struct device *dev = musb->controller; struct omap2430_glue *glue = dev_get_drvdata(dev->parent); - struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev); - struct omap_musb_board_data *data = pdata->board_data; - switch (glue->status) { case MUSB_ID_GROUND: omap_control_usb_set_mode(glue->control_otghs, USB_MODE_HOST); - if (data->interface_type != MUSB_INTERFACE_UTMI) - break; - devctl = musb_readb(musb->mregs, MUSB_DEVCTL); - /* start the session */ - devctl |= MUSB_DEVCTL_SESSION; - musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); - while (musb_readb(musb->mregs, MUSB_DEVCTL) & - MUSB_DEVCTL_BDEVICE) { - cpu_relax(); - - if (time_after(jiffies, timeout)) { - dev_err(dev, "configured as A device timeout"); - break; - } - } break; case MUSB_VBUS_VALID: -- cgit v1.2.3-59-g8ed1b From 8b359cbc3cdeb6145ca096334509df2a49ebaa0e Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 15 Jan 2020 07:25:31 -0600 Subject: usb: musb: omap2430: Idle musb on init We want to configure musb state in omap2430_musb_enable() instead of omap2430_musb_init(). Otherwise musb may not idle properly until USB cable has been connected at least once. And we already have omap_musb_set_mailbox() configure mode with omap_control_usb_set_mode() so we can remove those calls from omap2430_musb_enable(). Cc: Jacopo Mondi Cc: Marcel Partap Cc: Merlijn Wajer Cc: Michael Scott Cc: NeKit Cc: Pavel Machek Cc: Sebastian Reichel Acked-by: Pavel Machek Signed-off-by: Tony Lindgren Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-10-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/omap2430.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 2cc54135bb8b..bc5810e14ebb 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -212,7 +212,6 @@ static int omap2430_musb_init(struct musb *musb) u32 l; int status = 0; struct device *dev = musb->controller; - struct omap2430_glue *glue = dev_get_drvdata(dev->parent); struct musb_hdrc_platform_data *plat = dev_get_platdata(dev); struct omap_musb_board_data *data = plat->board_data; @@ -268,9 +267,6 @@ static int omap2430_musb_init(struct musb *musb) musb_readl(musb->mregs, OTG_INTERFSEL), musb_readl(musb->mregs, OTG_SIMENABLE)); - if (glue->status != MUSB_UNKNOWN) - omap_musb_set_mailbox(glue); - return 0; } @@ -279,19 +275,9 @@ static void omap2430_musb_enable(struct musb *musb) struct device *dev = musb->controller; struct omap2430_glue *glue = dev_get_drvdata(dev->parent); - switch (glue->status) { - - case MUSB_ID_GROUND: - omap_control_usb_set_mode(glue->control_otghs, USB_MODE_HOST); - break; - - case MUSB_VBUS_VALID: - omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE); - break; - - default: - break; - } + if (glue->status == MUSB_UNKNOWN) + glue->status = MUSB_VBUS_OFF; + omap_musb_set_mailbox(glue); } static void omap2430_musb_disable(struct musb *musb) -- cgit v1.2.3-59-g8ed1b From 98827105d8c32fffd22d963c493fc3f61388e939 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 15 Jan 2020 07:25:32 -0600 Subject: usb: musb: Get rid of omap2430_musb_set_vbus() Now that we've removed direct calls from interrupt handler to omap2430_musb_set_vbus(), let's make things less confusing and configure VBUS directly in omap_musb_set_mailbox(). We have omap_musb_set_mailbox() called from the PHYs, and that's all we need. Note that we can now also drop the check for MUSB_INTERFACE_UTMI, we've been already calling otg_set_vbus(musb->xceiv->otg, 0) unconditionally via omap2430_musb_set_vbus() and we should only need to call it once. And we want to disable VBUS unconditionally on disconnect even without musb->gadget_driver, so let's drop that check too. Acked-by: Pavel Machek Signed-off-by: Tony Lindgren Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-11-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/omap2430.c | 71 +++++++++++++++------------------------------ 1 file changed, 23 insertions(+), 48 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index bc5810e14ebb..d62c78b97cad 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -38,42 +38,6 @@ struct omap2430_glue { static struct omap2430_glue *_glue; -/* - * HDRC controls CPEN, but beware current surges during device connect. - * They can trigger transient overcurrent conditions that must be ignored. - * - * Note that we're skipping A_WAIT_VFALL -> A_IDLE and jumping right to B_IDLE - * as set by musb_set_peripheral(). - */ -static void omap2430_musb_set_vbus(struct musb *musb, int is_on) -{ - struct usb_otg *otg = musb->xceiv->otg; - int error; - - if (is_on) { - switch (musb->xceiv->otg->state) { - case OTG_STATE_A_IDLE: - error = musb_set_host(musb); - if (!error) { - musb->xceiv->otg->state = - OTG_STATE_A_WAIT_VRISE; - otg_set_vbus(otg, 1); - } - break; - default: - otg_set_vbus(otg, 1); - break; - } - } else { - error = musb_set_peripheral(musb); - otg_set_vbus(otg, 0); - } - - dev_dbg(musb->controller, "VBUS %s, devctl %02x\n", - usb_otg_state_string(musb->xceiv->otg->state), - musb_readb(musb->mregs, MUSB_DEVCTL)); -} - static inline void omap2430_low_level_exit(struct musb *musb) { u32 l; @@ -113,27 +77,42 @@ static int omap2430_musb_mailbox(enum musb_vbus_id_status status) return 0; } +/* + * HDRC controls CPEN, but beware current surges during device connect. + * They can trigger transient overcurrent conditions that must be ignored. + * + * Note that we're skipping A_WAIT_VFALL -> A_IDLE and jumping right to B_IDLE + * as set by musb_set_peripheral(). + */ static void omap_musb_set_mailbox(struct omap2430_glue *glue) { struct musb *musb = glue_to_musb(glue); - struct musb_hdrc_platform_data *pdata = - dev_get_platdata(musb->controller); - struct omap_musb_board_data *data = pdata->board_data; + int error; pm_runtime_get_sync(musb->controller); + + dev_dbg(musb->controller, "VBUS %s, devctl %02x\n", + usb_otg_state_string(musb->xceiv->otg->state), + musb_readb(musb->mregs, MUSB_DEVCTL)); + switch (glue->status) { case MUSB_ID_GROUND: dev_dbg(musb->controller, "ID GND\n"); switch (musb->xceiv->otg->state) { + case OTG_STATE_A_IDLE: + error = musb_set_host(musb); + if (error) + break; + musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; + /* Fall through */ case OTG_STATE_A_WAIT_VRISE: case OTG_STATE_A_WAIT_BCON: case OTG_STATE_A_HOST: - case OTG_STATE_A_IDLE: /* * On multiple ID ground interrupts just keep enabling * VBUS. At least cpcap VBUS shuts down otherwise. */ - omap2430_musb_set_vbus(musb, 1); + otg_set_vbus(musb->xceiv->otg, 1); break; default: musb->xceiv->otg->state = OTG_STATE_A_IDLE; @@ -141,7 +120,7 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) if (musb->gadget_driver) { omap_control_usb_set_mode(glue->control_otghs, USB_MODE_HOST); - omap2430_musb_set_vbus(musb, 1); + otg_set_vbus(musb->xceiv->otg, 1); } break; } @@ -160,12 +139,8 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) dev_dbg(musb->controller, "VBUS Disconnect\n"); musb->xceiv->last_event = USB_EVENT_NONE; - if (musb->gadget_driver) - omap2430_musb_set_vbus(musb, 0); - - if (data->interface_type == MUSB_INTERFACE_UTMI) - otg_set_vbus(musb->xceiv->otg, 0); - + musb_set_peripheral(musb); + otg_set_vbus(musb->xceiv->otg, 0); omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DISCONNECT); break; -- cgit v1.2.3-59-g8ed1b From 7e2ee1ab023cda87aa5f738076d83671484204d3 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Wed, 15 Jan 2020 07:25:33 -0600 Subject: usb: musb: jz4740: Suppress useless field in priv structure The 'dev' field was never read anywhere. Signed-off-by: Paul Cercueil Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-12-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/jz4740.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/jz4740.c b/drivers/usb/musb/jz4740.c index e3b8c84ccdb8..03c555679e5e 100644 --- a/drivers/usb/musb/jz4740.c +++ b/drivers/usb/musb/jz4740.c @@ -17,7 +17,6 @@ #include "musb_core.h" struct jz4740_glue { - struct device *dev; struct platform_device *musb; struct clk *clk; }; @@ -141,7 +140,6 @@ static int jz4740_probe(struct platform_device *pdev) musb->dev.parent = &pdev->dev; - glue->dev = &pdev->dev; glue->musb = musb; glue->clk = clk; -- cgit v1.2.3-59-g8ed1b From 4b70331b6fa13e4ae6ba634c336a616a7e2bf9d0 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Wed, 15 Jan 2020 07:25:34 -0600 Subject: usb: musb: jz4740: Add local dev variable to clean up probe Clean up the probe function by using a local 'struct device *dev' variable, instead of referencing &pdev->dev everytime. Signed-off-by: Paul Cercueil Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-13-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/jz4740.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/jz4740.c b/drivers/usb/musb/jz4740.c index 03c555679e5e..9aca12f99c9f 100644 --- a/drivers/usb/musb/jz4740.c +++ b/drivers/usb/musb/jz4740.c @@ -109,36 +109,37 @@ static const struct musb_platform_ops jz4740_musb_ops = { static int jz4740_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct musb_hdrc_platform_data *pdata = &jz4740_musb_platform_data; struct platform_device *musb; struct jz4740_glue *glue; struct clk *clk; int ret; - glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL); + glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL); if (!glue) return -ENOMEM; musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO); if (!musb) { - dev_err(&pdev->dev, "failed to allocate musb device\n"); + dev_err(dev, "failed to allocate musb device"); return -ENOMEM; } - clk = devm_clk_get(&pdev->dev, "udc"); + clk = devm_clk_get(dev, "udc"); if (IS_ERR(clk)) { - dev_err(&pdev->dev, "failed to get clock\n"); + dev_err(dev, "failed to get clock"); ret = PTR_ERR(clk); goto err_platform_device_put; } ret = clk_prepare_enable(clk); if (ret) { - dev_err(&pdev->dev, "failed to enable clock\n"); + dev_err(dev, "failed to enable clock"); goto err_platform_device_put; } - musb->dev.parent = &pdev->dev; + musb->dev.parent = dev; glue->musb = musb; glue->clk = clk; @@ -150,19 +151,19 @@ static int jz4740_probe(struct platform_device *pdev) ret = platform_device_add_resources(musb, pdev->resource, pdev->num_resources); if (ret) { - dev_err(&pdev->dev, "failed to add resources\n"); + dev_err(dev, "failed to add resources"); goto err_clk_disable; } ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); if (ret) { - dev_err(&pdev->dev, "failed to add platform_data\n"); + dev_err(dev, "failed to add platform_data"); goto err_clk_disable; } ret = platform_device_add(musb); if (ret) { - dev_err(&pdev->dev, "failed to register musb device\n"); + dev_err(dev, "failed to register musb device"); goto err_clk_disable; } -- cgit v1.2.3-59-g8ed1b From 31cecb6bb6982e2976d3f95bd0d44855ec52cc29 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Wed, 15 Jan 2020 07:25:35 -0600 Subject: usb: musb: jz4740: Constify jz4740_musb_pdata struct By moving around the jz4740_musb_pdata structure, we can have the .platform_ops field initialized, so that we don't have to initialize it manually in the probe function. Therefore, the struct can be const now. Signed-off-by: Paul Cercueil Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-14-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/jz4740.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/jz4740.c b/drivers/usb/musb/jz4740.c index 9aca12f99c9f..1400e5763d44 100644 --- a/drivers/usb/musb/jz4740.c +++ b/drivers/usb/musb/jz4740.c @@ -66,11 +66,6 @@ static const struct musb_hdrc_config jz4740_musb_config = { .fifo_cfg_size = ARRAY_SIZE(jz4740_musb_fifo_cfg), }; -static struct musb_hdrc_platform_data jz4740_musb_platform_data = { - .mode = MUSB_PERIPHERAL, - .config = &jz4740_musb_config, -}; - static int jz4740_musb_init(struct musb *musb) { struct device *dev = musb->controller->parent; @@ -107,10 +102,16 @@ static const struct musb_platform_ops jz4740_musb_ops = { .init = jz4740_musb_init, }; +static const struct musb_hdrc_platform_data jz4740_musb_pdata = { + .mode = MUSB_PERIPHERAL, + .config = &jz4740_musb_config, + .platform_ops = &jz4740_musb_ops, +}; + static int jz4740_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct musb_hdrc_platform_data *pdata = &jz4740_musb_platform_data; + const struct musb_hdrc_platform_data *pdata = &jz4740_musb_pdata; struct platform_device *musb; struct jz4740_glue *glue; struct clk *clk; @@ -144,8 +145,6 @@ static int jz4740_probe(struct platform_device *pdev) glue->musb = musb; glue->clk = clk; - pdata->platform_ops = &jz4740_musb_ops; - platform_set_drvdata(pdev, glue); ret = platform_device_add_resources(musb, pdev->resource, -- cgit v1.2.3-59-g8ed1b From 90fad5d7621e8edc9f8bb096c387a09cb563284c Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Wed, 15 Jan 2020 07:25:36 -0600 Subject: usb: musb: jz4740: Rename platform_device field in priv struct Name the platform_device pointer 'pdev' instead of 'musb'. Since the driver also deal with pointers to 'struct musb', it can be very confusing to have a pointer named after this struct but with a different type. Signed-off-by: Paul Cercueil Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-15-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/jz4740.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/jz4740.c b/drivers/usb/musb/jz4740.c index 1400e5763d44..64e0b0f8c45b 100644 --- a/drivers/usb/musb/jz4740.c +++ b/drivers/usb/musb/jz4740.c @@ -17,7 +17,7 @@ #include "musb_core.h" struct jz4740_glue { - struct platform_device *musb; + struct platform_device *pdev; struct clk *clk; }; @@ -142,7 +142,7 @@ static int jz4740_probe(struct platform_device *pdev) musb->dev.parent = dev; - glue->musb = musb; + glue->pdev = musb; glue->clk = clk; platform_set_drvdata(pdev, glue); @@ -179,7 +179,7 @@ static int jz4740_remove(struct platform_device *pdev) { struct jz4740_glue *glue = platform_get_drvdata(pdev); - platform_device_unregister(glue->musb); + platform_device_unregister(glue->pdev); clk_disable_unprepare(glue->clk); return 0; -- cgit v1.2.3-59-g8ed1b From 94203e1a1a254743b9c8ac2755be86ac02496966 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Wed, 15 Jan 2020 07:25:37 -0600 Subject: usb: musb: jz4740: Comments fix Add a /* sentinel */ comment to the sentinel entry of the devicetree ID table, and fix a multi-line comment not having its opening token on a separate line. Signed-off-by: Paul Cercueil Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-16-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/jz4740.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/jz4740.c b/drivers/usb/musb/jz4740.c index 64e0b0f8c45b..b4884575e37a 100644 --- a/drivers/usb/musb/jz4740.c +++ b/drivers/usb/musb/jz4740.c @@ -82,7 +82,8 @@ static int jz4740_musb_init(struct musb *musb) return err; } - /* Silicon does not implement ConfigData register. + /* + * Silicon does not implement ConfigData register. * Set dyn_fifo to avoid reading EP config from hardware. */ musb->dyn_fifo = true; @@ -188,7 +189,7 @@ static int jz4740_remove(struct platform_device *pdev) #ifdef CONFIG_OF static const struct of_device_id jz4740_musb_of_match[] = { { .compatible = "ingenic,jz4740-musb" }, - {}, + { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, jz4740_musb_of_match); #endif -- cgit v1.2.3-59-g8ed1b From 3fc32907b8ab688c26d7b213e866412379f73db7 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Wed, 15 Jan 2020 07:25:38 -0600 Subject: usb: musb: jz4740: Whitespace and indentation fixes Fix lines with too much or not enough indentation, and lines which were indented with spaces instead of tabs. Signed-off-by: Paul Cercueil Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-17-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/jz4740.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/jz4740.c b/drivers/usb/musb/jz4740.c index b4884575e37a..bc0109f4700b 100644 --- a/drivers/usb/musb/jz4740.c +++ b/drivers/usb/musb/jz4740.c @@ -23,9 +23,9 @@ struct jz4740_glue { static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci) { - unsigned long flags; - irqreturn_t retval = IRQ_NONE; - struct musb *musb = __hci; + unsigned long flags; + irqreturn_t retval = IRQ_NONE; + struct musb *musb = __hci; spin_lock_irqsave(&musb->lock, flags); @@ -39,7 +39,7 @@ static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci) * never see them set */ musb->int_usb &= MUSB_INTR_SUSPEND | MUSB_INTR_RESUME | - MUSB_INTR_RESET | MUSB_INTR_SOF; + MUSB_INTR_RESET | MUSB_INTR_SOF; if (musb->int_usb || musb->int_tx || musb->int_rx) retval = musb_interrupt(musb); @@ -50,20 +50,20 @@ static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci) } static struct musb_fifo_cfg jz4740_musb_fifo_cfg[] = { -{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, -{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, -{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 64, }, + { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 64, }, }; static const struct musb_hdrc_config jz4740_musb_config = { /* Silicon does not implement USB OTG. */ - .multipoint = 0, + .multipoint = 0, /* Max EPs scanned, driver will decide which EP can be used. */ - .num_eps = 4, + .num_eps = 4, /* RAMbits needed to configure EPs from table */ - .ram_bits = 9, - .fifo_cfg = jz4740_musb_fifo_cfg, - .fifo_cfg_size = ARRAY_SIZE(jz4740_musb_fifo_cfg), + .ram_bits = 9, + .fifo_cfg = jz4740_musb_fifo_cfg, + .fifo_cfg_size = ARRAY_SIZE(jz4740_musb_fifo_cfg), }; static int jz4740_musb_init(struct musb *musb) @@ -115,7 +115,7 @@ static int jz4740_probe(struct platform_device *pdev) const struct musb_hdrc_platform_data *pdata = &jz4740_musb_pdata; struct platform_device *musb; struct jz4740_glue *glue; - struct clk *clk; + struct clk *clk; int ret; glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL); @@ -178,7 +178,7 @@ err_platform_device_put: static int jz4740_remove(struct platform_device *pdev) { - struct jz4740_glue *glue = platform_get_drvdata(pdev); + struct jz4740_glue *glue = platform_get_drvdata(pdev); platform_device_unregister(glue->pdev); clk_disable_unprepare(glue->clk); -- cgit v1.2.3-59-g8ed1b From 3709ff5dc35203c5e93424941fa660e770a1e728 Mon Sep 17 00:00:00 2001 From: "Ben Dooks (Codethink)" Date: Wed, 15 Jan 2020 07:25:39 -0600 Subject: USB: musb: fix __iomem in trace functions The trace functions should have __iomem on the addr pointers. Add __iomem to avoid the following warnings from sparse: drivers/usb/musb/musb_core.c:253:55: warning: incorrect type in argument 2 (different address spaces) drivers/usb/musb/musb_core.c:253:55: expected void const *addr drivers/usb/musb/musb_core.c:253:55: got void const [noderef] *addr drivers/usb/musb/musb_core.c:259:56: warning: incorrect type in argument 2 (different address spaces) drivers/usb/musb/musb_core.c:259:56: expected void const *addr drivers/usb/musb/musb_core.c:259:56: got void [noderef] *addr drivers/usb/musb/musb_core.c:267:55: warning: incorrect type in argument 2 (different address spaces) drivers/usb/musb/musb_core.c:267:55: expected void const *addr drivers/usb/musb/musb_core.c:267:55: got void const [noderef] *addr drivers/usb/musb/musb_core.c:273:56: warning: incorrect type in argument 2 (different address spaces) drivers/usb/musb/musb_core.c:273:56: expected void const *addr drivers/usb/musb/musb_core.c:273:56: got void [noderef] *addr drivers/usb/musb/musb_core.c:383:55: warning: incorrect type in argument 2 (different address spaces) drivers/usb/musb/musb_core.c:383:55: expected void const *addr drivers/usb/musb/musb_core.c:383:55: got void const [noderef] *addr drivers/usb/musb/musb_core.c:390:56: warning: incorrect type in argument 2 (different address spaces) drivers/usb/musb/musb_core.c:390:56: expected void const *addr drivers/usb/musb/musb_core.c:390:56: got void [noderef] *addr Signed-off-by: Ben Dooks (Codethink) Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-18-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_trace.h | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_trace.h b/drivers/usb/musb/musb_trace.h index a97d618fe8ff..b193daf69685 100644 --- a/drivers/usb/musb/musb_trace.h +++ b/drivers/usb/musb/musb_trace.h @@ -38,11 +38,12 @@ TRACE_EVENT(musb_log, ); DECLARE_EVENT_CLASS(musb_regb, - TP_PROTO(void *caller, const void *addr, unsigned int offset, u8 data), + TP_PROTO(void *caller, const void __iomem *addr, + unsigned int offset, u8 data), TP_ARGS(caller, addr, offset, data), TP_STRUCT__entry( __field(void *, caller) - __field(const void *, addr) + __field(const void __iomem *, addr) __field(unsigned int, offset) __field(u8, data) ), @@ -57,21 +58,24 @@ DECLARE_EVENT_CLASS(musb_regb, ); DEFINE_EVENT(musb_regb, musb_readb, - TP_PROTO(void *caller, const void *addr, unsigned int offset, u8 data), + TP_PROTO(void *caller, const void __iomem *addr, + unsigned int offset, u8 data), TP_ARGS(caller, addr, offset, data) ); DEFINE_EVENT(musb_regb, musb_writeb, - TP_PROTO(void *caller, const void *addr, unsigned int offset, u8 data), + TP_PROTO(void *caller, const void __iomem *addr, + unsigned int offset, u8 data), TP_ARGS(caller, addr, offset, data) ); DECLARE_EVENT_CLASS(musb_regw, - TP_PROTO(void *caller, const void *addr, unsigned int offset, u16 data), + TP_PROTO(void *caller, const void __iomem *addr, + unsigned int offset, u16 data), TP_ARGS(caller, addr, offset, data), TP_STRUCT__entry( __field(void *, caller) - __field(const void *, addr) + __field(const void __iomem *, addr) __field(unsigned int, offset) __field(u16, data) ), @@ -86,21 +90,24 @@ DECLARE_EVENT_CLASS(musb_regw, ); DEFINE_EVENT(musb_regw, musb_readw, - TP_PROTO(void *caller, const void *addr, unsigned int offset, u16 data), + TP_PROTO(void *caller, const void __iomem *addr, + unsigned int offset, u16 data), TP_ARGS(caller, addr, offset, data) ); DEFINE_EVENT(musb_regw, musb_writew, - TP_PROTO(void *caller, const void *addr, unsigned int offset, u16 data), + TP_PROTO(void *caller, const void __iomem *addr, + unsigned int offset, u16 data), TP_ARGS(caller, addr, offset, data) ); DECLARE_EVENT_CLASS(musb_regl, - TP_PROTO(void *caller, const void *addr, unsigned int offset, u32 data), + TP_PROTO(void *caller, const void __iomem *addr, + unsigned int offset, u32 data), TP_ARGS(caller, addr, offset, data), TP_STRUCT__entry( __field(void *, caller) - __field(const void *, addr) + __field(const void __iomem *, addr) __field(unsigned int, offset) __field(u32, data) ), @@ -115,12 +122,14 @@ DECLARE_EVENT_CLASS(musb_regl, ); DEFINE_EVENT(musb_regl, musb_readl, - TP_PROTO(void *caller, const void *addr, unsigned int offset, u32 data), + TP_PROTO(void *caller, const void __iomem *addr, + unsigned int offset, u32 data), TP_ARGS(caller, addr, offset, data) ); DEFINE_EVENT(musb_regl, musb_writel, - TP_PROTO(void *caller, const void *addr, unsigned int offset, u32 data), + TP_PROTO(void *caller, const void __iomem *addr, + unsigned int offset, u32 data), TP_ARGS(caller, addr, offset, data) ); -- cgit v1.2.3-59-g8ed1b From b7962fb45f8fe0678b2d2eaa48382ea32fcf9400 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 15 Jan 2020 07:25:40 -0600 Subject: usb: musb/ux500: Use dma_request_chan() instead dma_request_slave_channel() dma_request_slave_channel() is a wrapper on top of dma_request_chan() eating up the error code. Signed-off-by: Peter Ujfalusi Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-19-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/ux500_dma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c index d19bb3e89da6..d5cf5e8bb1ca 100644 --- a/drivers/usb/musb/ux500_dma.c +++ b/drivers/usb/musb/ux500_dma.c @@ -310,9 +310,9 @@ static int ux500_dma_controller_start(struct ux500_dma_controller *controller) dma_channel->max_len = SZ_16M; ux500_channel->dma_chan = - dma_request_slave_channel(dev, chan_names[ch_num]); + dma_request_chan(dev, chan_names[ch_num]); - if (!ux500_channel->dma_chan) + if (IS_ERR(ux500_channel->dma_chan)) ux500_channel->dma_chan = dma_request_channel(mask, data ? -- cgit v1.2.3-59-g8ed1b From fe3bbd6b383fbc62128fd1fe850105080cb4c9da Mon Sep 17 00:00:00 2001 From: Min Guo Date: Wed, 15 Jan 2020 07:25:42 -0600 Subject: usb: musb: Add get/set toggle hooks Add get/set toggle hooks in struct musb_io and struct musb_platform_ops for special platform; remove function musb_save_toggle, use the set/get callback to handle toggle. Signed-off-by: Min Guo Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-21-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 42 ++++++++++++++++++++++++++++++++++++++++ drivers/usb/musb/musb_core.h | 5 +++++ drivers/usb/musb/musb_host.c | 46 ++++++++++---------------------------------- drivers/usb/musb/musb_io.h | 4 ++++ 4 files changed, 61 insertions(+), 36 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 34090707d122..f3c95cd12e04 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -275,6 +275,38 @@ static void musb_default_writew(void __iomem *addr, unsigned offset, u16 data) __raw_writew(data, addr + offset); } +static u16 musb_default_get_toggle(struct musb_qh *qh, int is_out) +{ + void __iomem *epio = qh->hw_ep->regs; + u16 csr; + + if (is_out) + csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE; + else + csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE; + + return csr; +} + +static u16 musb_default_set_toggle(struct musb_qh *qh, int is_out, + struct urb *urb) +{ + u16 csr; + u16 toggle; + + toggle = usb_gettoggle(urb->dev, qh->epnum, is_out); + + if (is_out) + csr = toggle ? (MUSB_TXCSR_H_WR_DATATOGGLE + | MUSB_TXCSR_H_DATATOGGLE) + : MUSB_TXCSR_CLRDATATOG; + else + csr = toggle ? (MUSB_RXCSR_H_WR_DATATOGGLE + | MUSB_RXCSR_H_DATATOGGLE) : 0; + + return csr; +} + /* * Load an endpoint's FIFO */ @@ -2381,6 +2413,16 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) else musb->io.write_fifo = musb_default_write_fifo; + if (musb->ops->get_toggle) + musb->io.get_toggle = musb->ops->get_toggle; + else + musb->io.get_toggle = musb_default_get_toggle; + + if (musb->ops->set_toggle) + musb->io.set_toggle = musb->ops->set_toggle; + else + musb->io.set_toggle = musb_default_set_toggle; + if (!musb->xceiv->io_ops) { musb->xceiv->io_dev = musb->controller; musb->xceiv->io_priv = musb->mregs; diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 8a13a46cd891..2e4fcf1a1a5c 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -27,6 +27,7 @@ struct musb; struct musb_hw_ep; struct musb_ep; +struct musb_qh; /* Helper defines for struct musb->hwvers */ #define MUSB_HWVERS_MAJOR(x) ((x >> 10) & 0x1f) @@ -123,6 +124,8 @@ struct musb_io; * @writew: write 16 bits * @read_fifo: reads the fifo * @write_fifo: writes to fifo + * @get_toggle: platform specific get toggle function + * @set_toggle: platform specific set toggle function * @dma_init: platform specific dma init function * @dma_exit: platform specific dma exit function * @init: turns on clocks, sets up platform-specific registers, etc @@ -167,6 +170,8 @@ struct musb_platform_ops { void (*writew)(void __iomem *addr, unsigned offset, u16 data); void (*read_fifo)(struct musb_hw_ep *hw_ep, u16 len, u8 *buf); void (*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf); + u16 (*get_toggle)(struct musb_qh *qh, int is_out); + u16 (*set_toggle)(struct musb_qh *qh, int is_out, struct urb *urb); struct dma_controller * (*dma_init) (struct musb *musb, void __iomem *base); void (*dma_exit)(struct dma_controller *c); diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 5a44b70372d9..886c9b602f8c 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -286,26 +286,6 @@ __acquires(musb->lock) spin_lock(&musb->lock); } -/* For bulk/interrupt endpoints only */ -static inline void musb_save_toggle(struct musb_qh *qh, int is_in, - struct urb *urb) -{ - void __iomem *epio = qh->hw_ep->regs; - u16 csr; - - /* - * FIXME: the current Mentor DMA code seems to have - * problems getting toggle correct. - */ - - if (is_in) - csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE; - else - csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE; - - usb_settoggle(urb->dev, qh->epnum, !is_in, csr ? 1 : 0); -} - /* * Advance this hardware endpoint's queue, completing the specified URB and * advancing to either the next URB queued to that qh, or else invalidating @@ -320,6 +300,7 @@ static void musb_advance_schedule(struct musb *musb, struct urb *urb, struct musb_hw_ep *ep = qh->hw_ep; int ready = qh->is_ready; int status; + u16 toggle; status = (urb->status == -EINPROGRESS) ? 0 : urb->status; @@ -327,7 +308,8 @@ static void musb_advance_schedule(struct musb *musb, struct urb *urb, switch (qh->type) { case USB_ENDPOINT_XFER_BULK: case USB_ENDPOINT_XFER_INT: - musb_save_toggle(qh, is_in, urb); + toggle = musb->io.get_toggle(qh, !is_in); + usb_settoggle(urb->dev, qh->epnum, !is_in, toggle ? 1 : 0); break; case USB_ENDPOINT_XFER_ISOC: if (status == 0 && urb->error_count) @@ -772,13 +754,8 @@ static void musb_ep_program(struct musb *musb, u8 epnum, ); csr |= MUSB_TXCSR_MODE; - if (!hw_ep->tx_double_buffered) { - if (usb_gettoggle(urb->dev, qh->epnum, 1)) - csr |= MUSB_TXCSR_H_WR_DATATOGGLE - | MUSB_TXCSR_H_DATATOGGLE; - else - csr |= MUSB_TXCSR_CLRDATATOG; - } + if (!hw_ep->tx_double_buffered) + csr |= musb->io.set_toggle(qh, is_out, urb); musb_writew(epio, MUSB_TXCSR, csr); /* REVISIT may need to clear FLUSHFIFO ... */ @@ -860,17 +837,12 @@ finish: /* IN/receive */ } else { - u16 csr; + u16 csr = 0; if (hw_ep->rx_reinit) { musb_rx_reinit(musb, qh, epnum); + csr |= musb->io.set_toggle(qh, is_out, urb); - /* init new state: toggle and NYET, maybe DMA later */ - if (usb_gettoggle(urb->dev, qh->epnum, 0)) - csr = MUSB_RXCSR_H_WR_DATATOGGLE - | MUSB_RXCSR_H_DATATOGGLE; - else - csr = 0; if (qh->type == USB_ENDPOINT_XFER_INT) csr |= MUSB_RXCSR_DISNYET; @@ -933,6 +905,7 @@ static void musb_bulk_nak_timeout(struct musb *musb, struct musb_hw_ep *ep, void __iomem *epio = ep->regs; struct musb_qh *cur_qh, *next_qh; u16 rx_csr, tx_csr; + u16 toggle; musb_ep_select(mbase, ep->epnum); if (is_in) { @@ -970,7 +943,8 @@ static void musb_bulk_nak_timeout(struct musb *musb, struct musb_hw_ep *ep, urb->actual_length += dma->actual_len; dma->actual_len = 0L; } - musb_save_toggle(cur_qh, is_in, urb); + toggle = musb->io.get_toggle(cur_qh, !is_in); + usb_settoggle(urb->dev, cur_qh->epnum, !is_in, toggle ? 1 : 0); if (is_in) { /* move cur_qh to end of queue */ diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h index 8058a58092cf..8179334f405b 100644 --- a/drivers/usb/musb/musb_io.h +++ b/drivers/usb/musb/musb_io.h @@ -22,6 +22,8 @@ * @read_fifo: platform specific function to read fifo * @write_fifo: platform specific function to write fifo * @busctl_offset: platform specific function to get busctl offset + * @get_toggle: platform specific function to get toggle + * @set_toggle: platform specific function to set toggle */ struct musb_io { u32 (*ep_offset)(u8 epnum, u16 offset); @@ -30,6 +32,8 @@ struct musb_io { void (*read_fifo)(struct musb_hw_ep *hw_ep, u16 len, u8 *buf); void (*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf); u32 (*busctl_offset)(u8 epnum, u16 offset); + u16 (*get_toggle)(struct musb_qh *qh, int is_out); + u16 (*set_toggle)(struct musb_qh *qh, int is_out, struct urb *urb); }; /* Do not add new entries here, add them the struct musb_io instead */ -- cgit v1.2.3-59-g8ed1b From edce61776c7e212d8b3d61e69afe7672efbacb04 Mon Sep 17 00:00:00 2001 From: Min Guo Date: Wed, 15 Jan 2020 07:25:43 -0600 Subject: usb: musb: Add noirq type of dma create interface Add noirq type of dma create interface for platform which do not have dedicated DMA interrupt line, move musbhsdma macro definition to musb_dma.h Signed-off-by: Min Guo Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-22-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_dma.h | 9 ++++++++ drivers/usb/musb/musbhsdma.c | 54 ++++++++++++++++++++++++++++++-------------- 2 files changed, 46 insertions(+), 17 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h index 8f60271c0a9d..4b4d8dc5d3f2 100644 --- a/drivers/usb/musb/musb_dma.h +++ b/drivers/usb/musb/musb_dma.h @@ -35,6 +35,12 @@ struct musb_hw_ep; * whether shared with the Inventra core or separate. */ +#define MUSB_HSDMA_BASE 0x200 +#define MUSB_HSDMA_INTR (MUSB_HSDMA_BASE + 0) +#define MUSB_HSDMA_CONTROL 0x4 +#define MUSB_HSDMA_ADDRESS 0x8 +#define MUSB_HSDMA_COUNT 0xc + #define DMA_ADDR_INVALID (~(dma_addr_t)0) #ifdef CONFIG_MUSB_PIO_ONLY @@ -191,6 +197,9 @@ extern void (*musb_dma_controller_destroy)(struct dma_controller *); extern struct dma_controller * musbhs_dma_controller_create(struct musb *musb, void __iomem *base); extern void musbhs_dma_controller_destroy(struct dma_controller *c); +extern struct dma_controller * +musbhs_dma_controller_create_noirq(struct musb *musb, void __iomem *base); +extern irqreturn_t dma_controller_irq(int irq, void *private_data); extern struct dma_controller * tusb_dma_controller_create(struct musb *musb, void __iomem *base); diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index 2d3751d885b4..bcc0fbf42ba8 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -10,12 +10,7 @@ #include #include #include "musb_core.h" - -#define MUSB_HSDMA_BASE 0x200 -#define MUSB_HSDMA_INTR (MUSB_HSDMA_BASE + 0) -#define MUSB_HSDMA_CONTROL 0x4 -#define MUSB_HSDMA_ADDRESS 0x8 -#define MUSB_HSDMA_COUNT 0xc +#include "musb_dma.h" #define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset) \ (MUSB_HSDMA_BASE + (_bchannel << 4) + _offset) @@ -268,7 +263,7 @@ static int dma_channel_abort(struct dma_channel *channel) return 0; } -static irqreturn_t dma_controller_irq(int irq, void *private_data) +irqreturn_t dma_controller_irq(int irq, void *private_data) { struct musb_dma_controller *controller = private_data; struct musb *musb = controller->private_data; @@ -383,6 +378,7 @@ done: spin_unlock_irqrestore(&musb->lock, flags); return retval; } +EXPORT_SYMBOL_GPL(dma_controller_irq); void musbhs_dma_controller_destroy(struct dma_controller *c) { @@ -398,18 +394,10 @@ void musbhs_dma_controller_destroy(struct dma_controller *c) } EXPORT_SYMBOL_GPL(musbhs_dma_controller_destroy); -struct dma_controller *musbhs_dma_controller_create(struct musb *musb, - void __iomem *base) +static struct musb_dma_controller * +dma_controller_alloc(struct musb *musb, void __iomem *base) { struct musb_dma_controller *controller; - struct device *dev = musb->controller; - struct platform_device *pdev = to_platform_device(dev); - int irq = platform_get_irq_byname(pdev, "dma"); - - if (irq <= 0) { - dev_err(dev, "No DMA interrupt line!\n"); - return NULL; - } controller = kzalloc(sizeof(*controller), GFP_KERNEL); if (!controller) @@ -423,6 +411,25 @@ struct dma_controller *musbhs_dma_controller_create(struct musb *musb, controller->controller.channel_release = dma_channel_release; controller->controller.channel_program = dma_channel_program; controller->controller.channel_abort = dma_channel_abort; + return controller; +} + +struct dma_controller * +musbhs_dma_controller_create(struct musb *musb, void __iomem *base) +{ + struct musb_dma_controller *controller; + struct device *dev = musb->controller; + struct platform_device *pdev = to_platform_device(dev); + int irq = platform_get_irq_byname(pdev, "dma"); + + if (irq <= 0) { + dev_err(dev, "No DMA interrupt line!\n"); + return NULL; + } + + controller = dma_controller_alloc(musb, base); + if (!controller) + return NULL; if (request_irq(irq, dma_controller_irq, 0, dev_name(musb->controller), controller)) { @@ -437,3 +444,16 @@ struct dma_controller *musbhs_dma_controller_create(struct musb *musb, return &controller->controller; } EXPORT_SYMBOL_GPL(musbhs_dma_controller_create); + +struct dma_controller * +musbhs_dma_controller_create_noirq(struct musb *musb, void __iomem *base) +{ + struct musb_dma_controller *controller; + + controller = dma_controller_alloc(musb, base); + if (!controller) + return NULL; + + return &controller->controller; +} +EXPORT_SYMBOL_GPL(musbhs_dma_controller_create_noirq); -- cgit v1.2.3-59-g8ed1b From 9c93d7fd464e7aad59c2afc261f80e6e0fbe2ca9 Mon Sep 17 00:00:00 2001 From: Min Guo Date: Wed, 15 Jan 2020 07:25:44 -0600 Subject: usb: musb: Add musb_clearb/w() interface Delete the const attribute of addr parameter in readb/w/l hooks, these changes are for implementing clearing W1C registers. Replace musb_readb/w with musb_clearb/w to clear the interrupt status. While at here, change some unsigned type to u32 to fix checkpatch.pl warnings. Signed-off-by: Min Guo [b-liu@ti.com: fix checkpatch.pl warnings.] Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-23-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 42 ++++++++++++++++++++++++++++-------------- drivers/usb/musb/musb_core.h | 12 ++++++++---- drivers/usb/musb/musb_io.h | 14 ++++++++------ drivers/usb/musb/musbhsdma.c | 2 +- drivers/usb/musb/sunxi.c | 4 ++-- drivers/usb/musb/tusb6010.c | 2 +- 6 files changed, 48 insertions(+), 28 deletions(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index f3c95cd12e04..71691a1f8ae3 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -247,7 +247,7 @@ static u32 musb_default_busctl_offset(u8 epnum, u16 offset) return 0x80 + (0x08 * epnum) + offset; } -static u8 musb_default_readb(const void __iomem *addr, unsigned offset) +static u8 musb_default_readb(void __iomem *addr, u32 offset) { u8 data = __raw_readb(addr + offset); @@ -255,13 +255,13 @@ static u8 musb_default_readb(const void __iomem *addr, unsigned offset) return data; } -static void musb_default_writeb(void __iomem *addr, unsigned offset, u8 data) +static void musb_default_writeb(void __iomem *addr, u32 offset, u8 data) { trace_musb_writeb(__builtin_return_address(0), addr, offset, data); __raw_writeb(data, addr + offset); } -static u16 musb_default_readw(const void __iomem *addr, unsigned offset) +static u16 musb_default_readw(void __iomem *addr, u32 offset) { u16 data = __raw_readw(addr + offset); @@ -269,7 +269,7 @@ static u16 musb_default_readw(const void __iomem *addr, unsigned offset) return data; } -static void musb_default_writew(void __iomem *addr, unsigned offset, u16 data) +static void musb_default_writew(void __iomem *addr, u32 offset, u16 data) { trace_musb_writew(__builtin_return_address(0), addr, offset, data); __raw_writew(data, addr + offset); @@ -397,19 +397,25 @@ static void musb_default_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) /* * Old style IO functions */ -u8 (*musb_readb)(const void __iomem *addr, unsigned offset); +u8 (*musb_readb)(void __iomem *addr, u32 offset); EXPORT_SYMBOL_GPL(musb_readb); -void (*musb_writeb)(void __iomem *addr, unsigned offset, u8 data); +void (*musb_writeb)(void __iomem *addr, u32 offset, u8 data); EXPORT_SYMBOL_GPL(musb_writeb); -u16 (*musb_readw)(const void __iomem *addr, unsigned offset); +u8 (*musb_clearb)(void __iomem *addr, u32 offset); +EXPORT_SYMBOL_GPL(musb_clearb); + +u16 (*musb_readw)(void __iomem *addr, u32 offset); EXPORT_SYMBOL_GPL(musb_readw); -void (*musb_writew)(void __iomem *addr, unsigned offset, u16 data); +void (*musb_writew)(void __iomem *addr, u32 offset, u16 data); EXPORT_SYMBOL_GPL(musb_writew); -u32 musb_readl(const void __iomem *addr, unsigned offset) +u16 (*musb_clearw)(void __iomem *addr, u32 offset); +EXPORT_SYMBOL_GPL(musb_clearw); + +u32 musb_readl(void __iomem *addr, u32 offset) { u32 data = __raw_readl(addr + offset); @@ -418,7 +424,7 @@ u32 musb_readl(const void __iomem *addr, unsigned offset) } EXPORT_SYMBOL_GPL(musb_readl); -void musb_writel(void __iomem *addr, unsigned offset, u32 data) +void musb_writel(void __iomem *addr, u32 offset, u32 data) { trace_musb_writel(__builtin_return_address(0), addr, offset, data); __raw_writel(data, addr + offset); @@ -1149,7 +1155,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, static void musb_disable_interrupts(struct musb *musb) { void __iomem *mbase = musb->mregs; - u16 temp; /* disable interrupts */ musb_writeb(mbase, MUSB_INTRUSBE, 0); @@ -1159,9 +1164,9 @@ static void musb_disable_interrupts(struct musb *musb) musb_writew(mbase, MUSB_INTRRXE, 0); /* flush pending interrupts */ - temp = musb_readb(mbase, MUSB_INTRUSB); - temp = musb_readw(mbase, MUSB_INTRTX); - temp = musb_readw(mbase, MUSB_INTRRX); + musb_clearb(mbase, MUSB_INTRUSB); + musb_clearw(mbase, MUSB_INTRTX); + musb_clearw(mbase, MUSB_INTRRX); } static void musb_enable_interrupts(struct musb *musb) @@ -2388,10 +2393,19 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) musb_readb = musb->ops->readb; if (musb->ops->writeb) musb_writeb = musb->ops->writeb; + if (musb->ops->clearb) + musb_clearb = musb->ops->clearb; + else + musb_clearb = musb_readb; + if (musb->ops->readw) musb_readw = musb->ops->readw; if (musb->ops->writew) musb_writew = musb->ops->writew; + if (musb->ops->clearw) + musb_clearw = musb->ops->clearw; + else + musb_clearw = musb_readw; #ifndef CONFIG_MUSB_PIO_ONLY if (!musb->ops->dma_init || !musb->ops->dma_exit) { diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 2e4fcf1a1a5c..290a2bc46606 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -120,8 +120,10 @@ struct musb_io; * @fifo_offset: returns the fifo offset * @readb: read 8 bits * @writeb: write 8 bits + * @clearb: could be clear-on-readb or W1C * @readw: read 16 bits * @writew: write 16 bits + * @clearw: could be clear-on-readw or W1C * @read_fifo: reads the fifo * @write_fifo: writes to fifo * @get_toggle: platform specific get toggle function @@ -164,10 +166,12 @@ struct musb_platform_ops { u16 fifo_mode; u32 (*fifo_offset)(u8 epnum); u32 (*busctl_offset)(u8 epnum, u16 offset); - u8 (*readb)(const void __iomem *addr, unsigned offset); - void (*writeb)(void __iomem *addr, unsigned offset, u8 data); - u16 (*readw)(const void __iomem *addr, unsigned offset); - void (*writew)(void __iomem *addr, unsigned offset, u16 data); + u8 (*readb)(void __iomem *addr, u32 offset); + void (*writeb)(void __iomem *addr, u32 offset, u8 data); + u8 (*clearb)(void __iomem *addr, u32 offset); + u16 (*readw)(void __iomem *addr, u32 offset); + void (*writew)(void __iomem *addr, u32 offset, u16 data); + u16 (*clearw)(void __iomem *addr, u32 offset); void (*read_fifo)(struct musb_hw_ep *hw_ep, u16 len, u8 *buf); void (*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf); u16 (*get_toggle)(struct musb_qh *qh, int is_out); diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h index 8179334f405b..f17aabd95a50 100644 --- a/drivers/usb/musb/musb_io.h +++ b/drivers/usb/musb/musb_io.h @@ -37,11 +37,13 @@ struct musb_io { }; /* Do not add new entries here, add them the struct musb_io instead */ -extern u8 (*musb_readb)(const void __iomem *addr, unsigned offset); -extern void (*musb_writeb)(void __iomem *addr, unsigned offset, u8 data); -extern u16 (*musb_readw)(const void __iomem *addr, unsigned offset); -extern void (*musb_writew)(void __iomem *addr, unsigned offset, u16 data); -extern u32 musb_readl(const void __iomem *addr, unsigned offset); -extern void musb_writel(void __iomem *addr, unsigned offset, u32 data); +extern u8 (*musb_readb)(void __iomem *addr, u32 offset); +extern void (*musb_writeb)(void __iomem *addr, u32 offset, u8 data); +extern u8 (*musb_clearb)(void __iomem *addr, u32 offset); +extern u16 (*musb_readw)(void __iomem *addr, u32 offset); +extern void (*musb_writew)(void __iomem *addr, u32 offset, u16 data); +extern u16 (*musb_clearw)(void __iomem *addr, u32 offset); +extern u32 musb_readl(void __iomem *addr, u32 offset); +extern void musb_writel(void __iomem *addr, u32 offset, u32 data); #endif diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index bcc0fbf42ba8..0aacfc8be5a1 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -284,7 +284,7 @@ irqreturn_t dma_controller_irq(int irq, void *private_data) spin_lock_irqsave(&musb->lock, flags); - int_hsdma = musb_readb(mbase, MUSB_HSDMA_INTR); + int_hsdma = musb_clearb(mbase, MUSB_HSDMA_INTR); if (!int_hsdma) { musb_dbg(musb, "spurious DMA irq"); diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c index a72665fbf111..f3f76f2ac63f 100644 --- a/drivers/usb/musb/sunxi.c +++ b/drivers/usb/musb/sunxi.c @@ -407,7 +407,7 @@ static u32 sunxi_musb_busctl_offset(u8 epnum, u16 offset) return SUNXI_MUSB_TXFUNCADDR + offset; } -static u8 sunxi_musb_readb(const void __iomem *addr, unsigned offset) +static u8 sunxi_musb_readb(void __iomem *addr, u32 offset) { struct sunxi_glue *glue; @@ -520,7 +520,7 @@ static void sunxi_musb_writeb(void __iomem *addr, unsigned offset, u8 data) (int)(addr - sunxi_musb->mregs)); } -static u16 sunxi_musb_readw(const void __iomem *addr, unsigned offset) +static u16 sunxi_musb_readw(void __iomem *addr, u32 offset) { if (addr == sunxi_musb->mregs) { /* generic control or fifo control reg access */ diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 39453287b5c3..5d449089e3ad 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -142,7 +142,7 @@ static void tusb_ep_select(void __iomem *mbase, u8 epnum) /* * TUSB6010 doesn't allow 8-bit access; 16-bit access is the minimum. */ -static u8 tusb_readb(const void __iomem *addr, unsigned offset) +static u8 tusb_readb(void __iomem *addr, u32 offset) { u16 tmp; u8 val; -- cgit v1.2.3-59-g8ed1b From 0990366bab3c6afb93b276106e1e24d4bc69db7b Mon Sep 17 00:00:00 2001 From: Min Guo Date: Wed, 15 Jan 2020 07:25:45 -0600 Subject: usb: musb: Add support for MediaTek musb controller This adds support for MediaTek musb controller in host, peripheral and otg mode. There are some quirk of MediaTek musb controller, such as: -W1C interrupt status registers -Private data toggle registers -No dedicated DMA interrupt line Signed-off-by: Min Guo Signed-off-by: Yonglong Wu Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-24-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/Kconfig | 9 +- drivers/usb/musb/Makefile | 1 + drivers/usb/musb/mediatek.c | 582 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 591 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/musb/mediatek.c (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 4678ebc889b5..63376d494f0f 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -115,6 +115,13 @@ config USB_MUSB_JZ4740 depends on USB_MUSB_GADGET depends on USB=n || USB_OTG_BLACKLIST_HUB +config USB_MUSB_MEDIATEK + tristate "MediaTek platforms" + depends on ARCH_MEDIATEK || COMPILE_TEST + depends on NOP_USB_XCEIV + depends on GENERIC_PHY + select USB_ROLE_SWITCH + config USB_MUSB_AM335X_CHILD tristate @@ -141,7 +148,7 @@ config USB_UX500_DMA config USB_INVENTRA_DMA bool 'Inventra' - depends on USB_MUSB_OMAP2PLUS + depends on USB_MUSB_OMAP2PLUS || USB_MUSB_MEDIATEK help Enable DMA transfers using Mentor's engine. diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile index 3a88c79e650c..63d82d0fab67 100644 --- a/drivers/usb/musb/Makefile +++ b/drivers/usb/musb/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_USB_MUSB_DA8XX) += da8xx.o obj-$(CONFIG_USB_MUSB_UX500) += ux500.o obj-$(CONFIG_USB_MUSB_JZ4740) += jz4740.o obj-$(CONFIG_USB_MUSB_SUNXI) += sunxi.o +obj-$(CONFIG_USB_MUSB_MEDIATEK) += mediatek.o obj-$(CONFIG_USB_MUSB_AM335X_CHILD) += musb_am335x.o diff --git a/drivers/usb/musb/mediatek.c b/drivers/usb/musb/mediatek.c new file mode 100644 index 000000000000..6b88c2f5d970 --- /dev/null +++ b/drivers/usb/musb/mediatek.c @@ -0,0 +1,582 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 MediaTek Inc. + * + * Author: + * Min Guo + * Yonglong Wu + */ + +#include +#include +#include +#include +#include +#include +#include +#include "musb_core.h" +#include "musb_dma.h" + +#define USB_L1INTS 0x00a0 +#define USB_L1INTM 0x00a4 +#define MTK_MUSB_TXFUNCADDR 0x0480 + +/* MediaTek controller toggle enable and status reg */ +#define MUSB_RXTOG 0x80 +#define MUSB_RXTOGEN 0x82 +#define MUSB_TXTOG 0x84 +#define MUSB_TXTOGEN 0x86 +#define MTK_TOGGLE_EN GENMASK(15, 0) + +#define TX_INT_STATUS BIT(0) +#define RX_INT_STATUS BIT(1) +#define USBCOM_INT_STATUS BIT(2) +#define DMA_INT_STATUS BIT(3) + +#define DMA_INTR_STATUS_MSK GENMASK(7, 0) +#define DMA_INTR_UNMASK_SET_MSK GENMASK(31, 24) + +struct mtk_glue { + struct device *dev; + struct musb *musb; + struct platform_device *musb_pdev; + struct platform_device *usb_phy; + struct phy *phy; + struct usb_phy *xceiv; + enum phy_mode phy_mode; + struct clk *main; + struct clk *mcu; + struct clk *univpll; + enum usb_role role; + struct usb_role_switch *role_sw; +}; + +static int mtk_musb_clks_get(struct mtk_glue *glue) +{ + struct device *dev = glue->dev; + + glue->main = devm_clk_get(dev, "main"); + if (IS_ERR(glue->main)) { + dev_err(dev, "fail to get main clock\n"); + return PTR_ERR(glue->main); + } + + glue->mcu = devm_clk_get(dev, "mcu"); + if (IS_ERR(glue->mcu)) { + dev_err(dev, "fail to get mcu clock\n"); + return PTR_ERR(glue->mcu); + } + + glue->univpll = devm_clk_get(dev, "univpll"); + if (IS_ERR(glue->univpll)) { + dev_err(dev, "fail to get univpll clock\n"); + return PTR_ERR(glue->univpll); + } + + return 0; +} + +static int mtk_musb_clks_enable(struct mtk_glue *glue) +{ + int ret; + + ret = clk_prepare_enable(glue->main); + if (ret) { + dev_err(glue->dev, "failed to enable main clock\n"); + goto err_main_clk; + } + + ret = clk_prepare_enable(glue->mcu); + if (ret) { + dev_err(glue->dev, "failed to enable mcu clock\n"); + goto err_mcu_clk; + } + + ret = clk_prepare_enable(glue->univpll); + if (ret) { + dev_err(glue->dev, "failed to enable univpll clock\n"); + goto err_univpll_clk; + } + + return 0; + +err_univpll_clk: + clk_disable_unprepare(glue->mcu); +err_mcu_clk: + clk_disable_unprepare(glue->main); +err_main_clk: + return ret; +} + +static void mtk_musb_clks_disable(struct mtk_glue *glue) +{ + clk_disable_unprepare(glue->univpll); + clk_disable_unprepare(glue->mcu); + clk_disable_unprepare(glue->main); +} + +static int musb_usb_role_sx_set(struct device *dev, enum usb_role role) +{ + struct mtk_glue *glue = dev_get_drvdata(dev); + struct musb *musb = glue->musb; + u8 devctl = readb(musb->mregs + MUSB_DEVCTL); + enum usb_role new_role; + + if (role == glue->role) + return 0; + + switch (role) { + case USB_ROLE_HOST: + musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; + glue->phy_mode = PHY_MODE_USB_HOST; + new_role = USB_ROLE_HOST; + if (glue->role == USB_ROLE_NONE) + phy_power_on(glue->phy); + + devctl |= MUSB_DEVCTL_SESSION; + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + MUSB_HST_MODE(musb); + break; + case USB_ROLE_DEVICE: + musb->xceiv->otg->state = OTG_STATE_B_IDLE; + glue->phy_mode = PHY_MODE_USB_DEVICE; + new_role = USB_ROLE_DEVICE; + devctl &= ~MUSB_DEVCTL_SESSION; + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + if (glue->role == USB_ROLE_NONE) + phy_power_on(glue->phy); + + MUSB_DEV_MODE(musb); + break; + case USB_ROLE_NONE: + glue->phy_mode = PHY_MODE_USB_OTG; + new_role = USB_ROLE_NONE; + devctl &= ~MUSB_DEVCTL_SESSION; + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + if (glue->role != USB_ROLE_NONE) + phy_power_off(glue->phy); + + break; + default: + dev_err(glue->dev, "Invalid State\n"); + return -EINVAL; + } + + glue->role = new_role; + phy_set_mode(glue->phy, glue->phy_mode); + + return 0; +} + +static enum usb_role musb_usb_role_sx_get(struct device *dev) +{ + struct mtk_glue *glue = dev_get_drvdata(dev); + + return glue->role; +} + +static int mtk_otg_switch_init(struct mtk_glue *glue) +{ + struct usb_role_switch_desc role_sx_desc = { 0 }; + + role_sx_desc.set = musb_usb_role_sx_set; + role_sx_desc.get = musb_usb_role_sx_get; + role_sx_desc.fwnode = dev_fwnode(glue->dev); + glue->role_sw = usb_role_switch_register(glue->dev, &role_sx_desc); + + return PTR_ERR_OR_ZERO(glue->role_sw); +} + +static void mtk_otg_switch_exit(struct mtk_glue *glue) +{ + return usb_role_switch_unregister(glue->role_sw); +} + +static irqreturn_t generic_interrupt(int irq, void *__hci) +{ + unsigned long flags; + irqreturn_t retval = IRQ_NONE; + struct musb *musb = __hci; + + spin_lock_irqsave(&musb->lock, flags); + musb->int_usb = musb_clearb(musb->mregs, MUSB_INTRUSB); + musb->int_rx = musb_clearw(musb->mregs, MUSB_INTRRX); + musb->int_tx = musb_clearw(musb->mregs, MUSB_INTRTX); + + if (musb->int_usb || musb->int_tx || musb->int_rx) + retval = musb_interrupt(musb); + + spin_unlock_irqrestore(&musb->lock, flags); + + return retval; +} + +static irqreturn_t mtk_musb_interrupt(int irq, void *dev_id) +{ + irqreturn_t retval = IRQ_NONE; + struct musb *musb = (struct musb *)dev_id; + u32 l1_ints; + + l1_ints = musb_readl(musb->mregs, USB_L1INTS) & + musb_readl(musb->mregs, USB_L1INTM); + + if (l1_ints & (TX_INT_STATUS | RX_INT_STATUS | USBCOM_INT_STATUS)) + retval = generic_interrupt(irq, musb); + +#if defined(CONFIG_USB_INVENTRA_DMA) + if (l1_ints & DMA_INT_STATUS) + retval = dma_controller_irq(irq, musb->dma_controller); +#endif + return retval; +} + +static u32 mtk_musb_busctl_offset(u8 epnum, u16 offset) +{ + return MTK_MUSB_TXFUNCADDR + offset + 8 * epnum; +} + +static u8 mtk_musb_clearb(void __iomem *addr, unsigned int offset) +{ + u8 data; + + /* W1C */ + data = musb_readb(addr, offset); + musb_writeb(addr, offset, data); + return data; +} + +static u16 mtk_musb_clearw(void __iomem *addr, unsigned int offset) +{ + u16 data; + + /* W1C */ + data = musb_readw(addr, offset); + musb_writew(addr, offset, data); + return data; +} + +static int mtk_musb_set_mode(struct musb *musb, u8 mode) +{ + struct device *dev = musb->controller; + struct mtk_glue *glue = dev_get_drvdata(dev->parent); + enum phy_mode new_mode; + enum usb_role new_role; + + switch (mode) { + case MUSB_HOST: + new_mode = PHY_MODE_USB_HOST; + new_role = USB_ROLE_HOST; + break; + case MUSB_PERIPHERAL: + new_mode = PHY_MODE_USB_DEVICE; + new_role = USB_ROLE_DEVICE; + break; + case MUSB_OTG: + new_mode = PHY_MODE_USB_OTG; + new_role = USB_ROLE_NONE; + break; + default: + dev_err(glue->dev, "Invalid mode request\n"); + return -EINVAL; + } + + if (glue->phy_mode == new_mode) + return 0; + + if (musb->port_mode != MUSB_OTG) { + dev_err(glue->dev, "Does not support changing modes\n"); + return -EINVAL; + } + + glue->role = new_role; + musb_usb_role_sx_set(dev, glue->role); + return 0; +} + +static int mtk_musb_init(struct musb *musb) +{ + struct device *dev = musb->controller; + struct mtk_glue *glue = dev_get_drvdata(dev->parent); + int ret; + + glue->musb = musb; + musb->phy = glue->phy; + musb->xceiv = glue->xceiv; + musb->is_host = false; + musb->isr = mtk_musb_interrupt; + + /* Set TX/RX toggle enable */ + musb_writew(musb->mregs, MUSB_TXTOGEN, MTK_TOGGLE_EN); + musb_writew(musb->mregs, MUSB_RXTOGEN, MTK_TOGGLE_EN); + + if (musb->port_mode == MUSB_OTG) { + ret = mtk_otg_switch_init(glue); + if (ret) + return ret; + } + + ret = phy_init(glue->phy); + if (ret) + goto err_phy_init; + + ret = phy_power_on(glue->phy); + if (ret) + goto err_phy_power_on; + + phy_set_mode(glue->phy, glue->phy_mode); + +#if defined(CONFIG_USB_INVENTRA_DMA) + musb_writel(musb->mregs, MUSB_HSDMA_INTR, + DMA_INTR_STATUS_MSK | DMA_INTR_UNMASK_SET_MSK); +#endif + musb_writel(musb->mregs, USB_L1INTM, TX_INT_STATUS | RX_INT_STATUS | + USBCOM_INT_STATUS | DMA_INT_STATUS); + return 0; + +err_phy_power_on: + phy_exit(glue->phy); +err_phy_init: + mtk_otg_switch_exit(glue); + return ret; +} + +static u16 mtk_musb_get_toggle(struct musb_qh *qh, int is_out) +{ + struct musb *musb = qh->hw_ep->musb; + u8 epnum = qh->hw_ep->epnum; + u16 toggle; + + toggle = musb_readw(musb->mregs, is_out ? MUSB_TXTOG : MUSB_RXTOG); + return toggle & (1 << epnum); +} + +static u16 mtk_musb_set_toggle(struct musb_qh *qh, int is_out, struct urb *urb) +{ + struct musb *musb = qh->hw_ep->musb; + u8 epnum = qh->hw_ep->epnum; + u16 value, toggle; + + toggle = usb_gettoggle(urb->dev, qh->epnum, is_out); + + if (is_out) { + value = musb_readw(musb->mregs, MUSB_TXTOG); + value |= toggle << epnum; + musb_writew(musb->mregs, MUSB_TXTOG, value); + } else { + value = musb_readw(musb->mregs, MUSB_RXTOG); + value |= toggle << epnum; + musb_writew(musb->mregs, MUSB_RXTOG, value); + } + + return 0; +} + +static int mtk_musb_exit(struct musb *musb) +{ + struct device *dev = musb->controller; + struct mtk_glue *glue = dev_get_drvdata(dev->parent); + + mtk_otg_switch_exit(glue); + phy_power_off(glue->phy); + phy_exit(glue->phy); + mtk_musb_clks_disable(glue); + + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + return 0; +} + +static const struct musb_platform_ops mtk_musb_ops = { + .quirks = MUSB_DMA_INVENTRA, + .init = mtk_musb_init, + .get_toggle = mtk_musb_get_toggle, + .set_toggle = mtk_musb_set_toggle, + .exit = mtk_musb_exit, +#ifdef CONFIG_USB_INVENTRA_DMA + .dma_init = musbhs_dma_controller_create_noirq, + .dma_exit = musbhs_dma_controller_destroy, +#endif + .clearb = mtk_musb_clearb, + .clearw = mtk_musb_clearw, + .busctl_offset = mtk_musb_busctl_offset, + .set_mode = mtk_musb_set_mode, +}; + +#define MTK_MUSB_MAX_EP_NUM 8 +#define MTK_MUSB_RAM_BITS 11 + +static struct musb_fifo_cfg mtk_musb_mode_cfg[] = { + { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 5, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 5, .style = FIFO_RX, .maxpacket = 512, }, + { .hw_ep_num = 6, .style = FIFO_TX, .maxpacket = 1024, }, + { .hw_ep_num = 6, .style = FIFO_RX, .maxpacket = 1024, }, + { .hw_ep_num = 7, .style = FIFO_TX, .maxpacket = 512, }, + { .hw_ep_num = 7, .style = FIFO_RX, .maxpacket = 64, }, +}; + +static const struct musb_hdrc_config mtk_musb_hdrc_config = { + .fifo_cfg = mtk_musb_mode_cfg, + .fifo_cfg_size = ARRAY_SIZE(mtk_musb_mode_cfg), + .multipoint = true, + .dyn_fifo = true, + .num_eps = MTK_MUSB_MAX_EP_NUM, + .ram_bits = MTK_MUSB_RAM_BITS, +}; + +static const struct platform_device_info mtk_dev_info = { + .name = "musb-hdrc", + .id = PLATFORM_DEVID_AUTO, + .dma_mask = DMA_BIT_MASK(32), +}; + +static int mtk_musb_probe(struct platform_device *pdev) +{ + struct musb_hdrc_platform_data *pdata; + struct mtk_glue *glue; + struct platform_device_info pinfo; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + int ret = -ENOMEM; + + glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL); + if (!glue) + return -ENOMEM; + + glue->dev = dev; + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + ret = of_platform_populate(np, NULL, NULL, dev); + if (ret) { + dev_err(dev, "failed to create child devices at %p\n", np); + return ret; + } + + ret = mtk_musb_clks_get(glue); + if (ret) + return ret; + + pdata->config = &mtk_musb_hdrc_config; + pdata->platform_ops = &mtk_musb_ops; + pdata->mode = usb_get_dr_mode(dev); + + if (IS_ENABLED(CONFIG_USB_MUSB_HOST)) + pdata->mode = USB_DR_MODE_HOST; + else if (IS_ENABLED(CONFIG_USB_MUSB_GADGET)) + pdata->mode = USB_DR_MODE_PERIPHERAL; + + switch (pdata->mode) { + case USB_DR_MODE_HOST: + glue->phy_mode = PHY_MODE_USB_HOST; + glue->role = USB_ROLE_HOST; + break; + case USB_DR_MODE_PERIPHERAL: + glue->phy_mode = PHY_MODE_USB_DEVICE; + glue->role = USB_ROLE_DEVICE; + break; + case USB_DR_MODE_OTG: + glue->phy_mode = PHY_MODE_USB_OTG; + glue->role = USB_ROLE_NONE; + break; + default: + dev_err(&pdev->dev, "Error 'dr_mode' property\n"); + return -EINVAL; + } + + glue->phy = devm_of_phy_get_by_index(dev, np, 0); + if (IS_ERR(glue->phy)) { + dev_err(dev, "fail to getting phy %ld\n", + PTR_ERR(glue->phy)); + return PTR_ERR(glue->phy); + } + + glue->usb_phy = usb_phy_generic_register(); + if (IS_ERR(glue->usb_phy)) { + dev_err(dev, "fail to registering usb-phy %ld\n", + PTR_ERR(glue->usb_phy)); + return PTR_ERR(glue->usb_phy); + } + + glue->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); + if (IS_ERR(glue->xceiv)) { + dev_err(dev, "fail to getting usb-phy %d\n", ret); + ret = PTR_ERR(glue->xceiv); + goto err_unregister_usb_phy; + } + + platform_set_drvdata(pdev, glue); + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); + + ret = mtk_musb_clks_enable(glue); + if (ret) + goto err_enable_clk; + + pinfo = mtk_dev_info; + pinfo.parent = dev; + pinfo.res = pdev->resource; + pinfo.num_res = pdev->num_resources; + pinfo.data = pdata; + pinfo.size_data = sizeof(*pdata); + + glue->musb_pdev = platform_device_register_full(&pinfo); + if (IS_ERR(glue->musb_pdev)) { + ret = PTR_ERR(glue->musb_pdev); + dev_err(dev, "failed to register musb device: %d\n", ret); + goto err_device_register; + } + + return 0; + +err_device_register: + mtk_musb_clks_disable(glue); +err_enable_clk: + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); +err_unregister_usb_phy: + usb_phy_generic_unregister(glue->usb_phy); + return ret; +} + +static int mtk_musb_remove(struct platform_device *pdev) +{ + struct mtk_glue *glue = platform_get_drvdata(pdev); + struct platform_device *usb_phy = glue->usb_phy; + + platform_device_unregister(glue->musb_pdev); + usb_phy_generic_unregister(usb_phy); + + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id mtk_musb_match[] = { + {.compatible = "mediatek,mtk-musb",}, + {}, +}; +MODULE_DEVICE_TABLE(of, mtk_musb_match); +#endif + +static struct platform_driver mtk_musb_driver = { + .probe = mtk_musb_probe, + .remove = mtk_musb_remove, + .driver = { + .name = "musb-mtk", + .of_match_table = of_match_ptr(mtk_musb_match), + }, +}; + +module_platform_driver(mtk_musb_driver); + +MODULE_DESCRIPTION("MediaTek MUSB Glue Layer"); +MODULE_AUTHOR("Min Guo "); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3-59-g8ed1b From 1ea1859f8498275aeee35acde77fcb566cd8b999 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 15 Jan 2020 07:25:46 -0600 Subject: usb: musb: davinci: Convert to use GPIO descriptor The DaVinci MUSB glue contains an optional GPIO line to control VBUS power, convert this to use a GPIO descriptor and augment the EVM board file to provide this descriptor. I can't get this driver to compile properly and it depends on broken but when I didn get it to compile brokenly, it did at least not complain about THIS code being broken so I don't think I broke the driver any more than what it already is. I did away with the ifdefs that do not work with multiplatform anyway so the day someone decides to resurrect the code, the path to get it working should be easier as well since DaVinci is now multiplatform. Cc: Sekhar Nori Cc: Bartosz Golaszewski Cc: Tony Lindgren Signed-off-by: Linus Walleij [b-liu@ti.com: fixed one instance still ref to global variable vbus_state] Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-25-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-davinci/board-dm644x-evm.c | 12 +++++++ drivers/usb/musb/davinci.c | 57 ++++++++++++++++++-------------- 2 files changed, 45 insertions(+), 24 deletions(-) (limited to 'drivers/usb/musb') diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c index 9d87d4e440ea..040c949414fa 100644 --- a/arch/arm/mach-davinci/board-dm644x-evm.c +++ b/arch/arm/mach-davinci/board-dm644x-evm.c @@ -823,6 +823,17 @@ static int davinci_phy_fixup(struct phy_device *phydev) #define HAS_NAND IS_ENABLED(CONFIG_MTD_NAND_DAVINCI) +#define GPIO_nVBUS_DRV 160 + +static struct gpiod_lookup_table dm644evm_usb_gpio_table = { + .dev_id = "musb-davinci", + .table = { + GPIO_LOOKUP("davinci_gpio", GPIO_nVBUS_DRV, NULL, + GPIO_ACTIVE_HIGH), + { } + }, +}; + static __init void davinci_evm_init(void) { int ret; @@ -875,6 +886,7 @@ static __init void davinci_evm_init(void) dm644x_init_asp(); /* irlml6401 switches over 1A, in under 8 msec */ + gpiod_add_lookup_table(&dm644evm_usb_gpio_table); davinci_setup_usb(1000, 8); if (IS_BUILTIN(CONFIG_PHYLIB)) { diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index fb6bbd254ab7..704435526394 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -25,10 +25,6 @@ #include "musb_core.h" -#ifdef CONFIG_MACH_DAVINCI_EVM -#define GPIO_nVBUS_DRV 160 -#endif - #include "davinci.h" #include "cppi_dma.h" @@ -40,6 +36,9 @@ struct davinci_glue { struct device *dev; struct platform_device *musb; struct clk *clk; + bool vbus_state; + struct gpio_desc *vbus; + struct work_struct vbus_work; }; /* REVISIT (PM) we should be able to keep the PHY in low power mode most @@ -135,43 +134,44 @@ static void davinci_musb_disable(struct musb *musb) * when J10 is out, and TI documents it as handling OTG. */ -#ifdef CONFIG_MACH_DAVINCI_EVM - -static int vbus_state = -1; - /* I2C operations are always synchronous, and require a task context. * With unloaded systems, using the shared workqueue seems to suffice * to satisfy the 100msec A_WAIT_VRISE timeout... */ -static void evm_deferred_drvvbus(struct work_struct *ignored) +static void evm_deferred_drvvbus(struct work_struct *work) { - gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); - vbus_state = !vbus_state; -} + struct davinci_glue *glue = container_of(work, struct davinci_glue, + vbus_work); -#endif /* EVM */ + gpiod_set_value_cansleep(glue->vbus, glue->vbus_state); + glue->vbus_state = !glue->vbus_state; +} -static void davinci_musb_source_power(struct musb *musb, int is_on, int immediate) +static void davinci_musb_source_power(struct musb *musb, int is_on, + int immediate) { -#ifdef CONFIG_MACH_DAVINCI_EVM + struct davinci_glue *glue = dev_get_drvdata(musb->controller->parent); + + /* This GPIO handling is entirely optional */ + if (!glue->vbus) + return; + if (is_on) is_on = 1; - if (vbus_state == is_on) + if (glue->vbus_state == is_on) return; - vbus_state = !is_on; /* 0/1 vs "-1 == unknown/init" */ + /* 0/1 vs "-1 == unknown/init" */ + glue->vbus_state = !is_on; if (machine_is_davinci_evm()) { - static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus); - if (immediate) - gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); + gpiod_set_value_cansleep(glue->vbus, glue->vbus_state); else - schedule_work(&evm_vbus_work); + schedule_work(&glue->vbus_work); } if (immediate) - vbus_state = is_on; -#endif + glue->vbus_state = is_on; } static void davinci_musb_set_vbus(struct musb *musb, int is_on) @@ -524,6 +524,15 @@ static int davinci_probe(struct platform_device *pdev) pdata->platform_ops = &davinci_ops; + glue->vbus = devm_gpiod_get_optional(&pdev->dev, NULL, GPIOD_OUT_LOW); + if (IS_ERR(glue->vbus)) { + ret = PTR_ERR(glue->vbus); + goto err0; + } else { + glue->vbus_state = -1; + INIT_WORK(&glue->vbus_work, evm_deferred_drvvbus); + } + usb_phy_generic_register(); platform_set_drvdata(pdev, glue); -- cgit v1.2.3-59-g8ed1b From 4baa550ecc86693106493bd92382e0edb8caf64d Mon Sep 17 00:00:00 2001 From: Bin Liu Date: Wed, 15 Jan 2020 07:25:47 -0600 Subject: usb: musb: remove dummy driver musb_am335x.c Since commit 0782e8572ce4 ("ARM: dts: Probe am335x musb with ti-sysc"), the dummy driver musb_am335x.c is no longer needed, let's drop it. Acked-by: Tony Lindgren Signed-off-by: Bin Liu Link: https://lore.kernel.org/r/20200115132547.364-26-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/Kconfig | 4 ---- drivers/usb/musb/Makefile | 3 --- drivers/usb/musb/musb_am335x.c | 44 ------------------------------------------ 3 files changed, 51 deletions(-) delete mode 100644 drivers/usb/musb/musb_am335x.c (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 63376d494f0f..eb2ded1026ee 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -101,7 +101,6 @@ config USB_MUSB_AM35X config USB_MUSB_DSPS tristate "TI DSPS platforms" - select USB_MUSB_AM335X_CHILD depends on ARCH_OMAP2PLUS || COMPILE_TEST depends on OF_IRQ @@ -122,9 +121,6 @@ config USB_MUSB_MEDIATEK depends on GENERIC_PHY select USB_ROLE_SWITCH -config USB_MUSB_AM335X_CHILD - tristate - comment "MUSB DMA mode" config MUSB_PIO_ONLY diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile index 63d82d0fab67..932247360a9f 100644 --- a/drivers/usb/musb/Makefile +++ b/drivers/usb/musb/Makefile @@ -26,9 +26,6 @@ obj-$(CONFIG_USB_MUSB_JZ4740) += jz4740.o obj-$(CONFIG_USB_MUSB_SUNXI) += sunxi.o obj-$(CONFIG_USB_MUSB_MEDIATEK) += mediatek.o - -obj-$(CONFIG_USB_MUSB_AM335X_CHILD) += musb_am335x.o - # the kconfig must guarantee that only one of the # possible I/O schemes will be enabled at a time ... # PIO only, or DMA (several potential schemes). diff --git a/drivers/usb/musb/musb_am335x.c b/drivers/usb/musb/musb_am335x.c deleted file mode 100644 index 5f04f8e3a640..000000000000 --- a/drivers/usb/musb/musb_am335x.c +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include -#include -#include - -static int am335x_child_probe(struct platform_device *pdev) -{ - int ret; - - pm_runtime_enable(&pdev->dev); - - ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); - if (ret) - goto err; - - return 0; -err: - pm_runtime_disable(&pdev->dev); - return ret; -} - -static const struct of_device_id am335x_child_of_match[] = { - { .compatible = "ti,am33xx-usb" }, - { }, -}; -MODULE_DEVICE_TABLE(of, am335x_child_of_match); - -static struct platform_driver am335x_child_driver = { - .probe = am335x_child_probe, - .driver = { - .name = "am335x-usb-childs", - .of_match_table = am335x_child_of_match, - }, -}; - -static int __init am335x_child_init(void) -{ - return platform_driver_register(&am335x_child_driver); -} -module_init(am335x_child_init); - -MODULE_DESCRIPTION("AM33xx child devices"); -MODULE_LICENSE("GPL v2"); -- cgit v1.2.3-59-g8ed1b From 1e31d3caa262cffa728e007ad209fb8e72b276a8 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 17 Jan 2020 09:31:24 +0000 Subject: usb: musb: fix spelling mistake: "periperal" -> "peripheral" There is a spelling mistake in a dev_err error message. Fix it. Signed-off-by: Colin Ian King Acked-by: Bin Liu Link: https://lore.kernel.org/r/20200117093124.97965-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb/musb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 71691a1f8ae3..f616fb489542 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -540,7 +540,7 @@ int musb_set_peripheral(struct musb *musb) devctl & MUSB_DEVCTL_BDEVICE, 5000, 1000000); if (error) { - dev_err(musb->controller, "%s: could not set periperal: %02x\n", + dev_err(musb->controller, "%s: could not set peripheral: %02x\n", __func__, devctl); return error; -- cgit v1.2.3-59-g8ed1b