Re: [PATCH 2/2] usb: musb: Fix getting a generic phy for musb_dsps
Hi Tony, On 02/06/2015 10:53 PM, Tony Lindgren wrote: * George Cherian [150206 05:05]: Hi Tony, You also need to add similar things in dsps_musb_reset(); Otherwise you might not recover from a BABBLE condition. Thank I totally missed that, updated patch below. Do you have some testcase that easily triggers BABBLE on MUSB? On a BBB or BBW you can connect a HUB with multiple device connected on HUB. Then do a repeated Connect and Disconnect of the HUB, This should trigger a BABBLE interrupt. Not all HUB's might not lead you to a BABBLE condition. Regards, Tony 8< -- From: Tony Lindgren Date: Wed, 4 Feb 2015 06:28:49 -0800 Subject: [PATCH] usb: musb: Fix getting a generic phy for musb_dsps We still have a combination of legacy phys and generic phys in use so we need to support both types of phy for musb_dsps.c. Cc: Brian Hutchinson Signed-off-by: Tony Lindgren --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -457,12 +457,27 @@ static int dsps_musb_init(struct musb *musb) if (IS_ERR(musb->xceiv)) return PTR_ERR(musb->xceiv); + musb->phy = devm_phy_get(dev->parent, "usb2-phy"); + /* Returns zero if e.g. not clocked */ rev = dsps_readl(reg_base, wrp->revision); if (!rev) return -ENODEV; usb_phy_init(musb->xceiv); + if (IS_ERR(musb->phy)) { + musb->phy = NULL; + } else { + ret = phy_init(musb->phy); + if (ret < 0) + return ret; + ret = phy_power_on(musb->phy); + if (ret) { + phy_exit(musb->phy); + return ret; + } + } + setup_timer(&glue->timer, otg_timer, (unsigned long) musb); /* Reset the musb */ @@ -502,6 +517,8 @@ static int dsps_musb_exit(struct musb *musb) del_timer_sync(&glue->timer); usb_phy_shutdown(musb->xceiv); + phy_power_off(musb->phy); + phy_exit(musb->phy); debugfs_remove_recursive(glue->dbgfs_root); return 0; @@ -610,7 +627,7 @@ static int dsps_musb_reset(struct musb *musb) struct device *dev = musb->controller; struct dsps_glue *glue = dev_get_drvdata(dev->parent); const struct dsps_musb_wrapper *wrp = glue->wrp; - int session_restart = 0; + int session_restart = 0, error; if (glue->sw_babble_enabled) session_restart = sw_babble_control(musb); @@ -624,8 +641,14 @@ static int dsps_musb_reset(struct musb *musb) dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset)); usleep_range(100, 200); usb_phy_shutdown(musb->xceiv); + error = phy_power_off(musb->phy); + if (error) + dev_err(dev, "phy shutdown failed: %i\n", error); usleep_range(100, 200); usb_phy_init(musb->xceiv); + error = phy_power_on(musb->phy); + if (error) + dev_err(dev, "phy powerup failed: %i\n", error); session_restart = 1; } -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/2] usb: musb: Fix getting a generic phy for musb_dsps
Hi Tony, You also need to add similar things in dsps_musb_reset(); Otherwise you might not recover from a BABBLE condition. On 02/05/2015 10:05 PM, Tony Lindgren wrote: We still have a combination of legacy phys and generic phys in use so we need to support both types of phy for musb_dsps.c. Cc: Brian Hutchinson Signed-off-by: Tony Lindgren --- drivers/usb/musb/musb_dsps.c | 17 + 1 file changed, 17 insertions(+) --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -457,12 +457,25 @@ static int dsps_musb_init(struct musb *musb) if (IS_ERR(musb->xceiv)) return PTR_ERR(musb->xceiv); + musb->phy = devm_phy_get(dev->parent, "usb2-phy"); + /* Returns zero if e.g. not clocked */ rev = dsps_readl(reg_base, wrp->revision); if (!rev) return -ENODEV; usb_phy_init(musb->xceiv); + if (IS_ERR(musb->phy)) { + musb->phy = NULL; + } else { + ret = phy_init(musb->phy); + if (ret < 0) + return ret; + ret = phy_power_on(musb->phy); + if (ret) + return ret; + } + setup_timer(&glue->timer, otg_timer, (unsigned long) musb); /* Reset the musb */ @@ -502,6 +515,10 @@ static int dsps_musb_exit(struct musb *musb) del_timer_sync(&glue->timer); usb_phy_shutdown(musb->xceiv); + if (musb->phy) { + phy_power_off(musb->phy); + phy_exit(musb->phy); + } debugfs_remove_recursive(glue->dbgfs_root); return 0; -George -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 02/19] usb: host xhci: fix up deallocation code
This fixes up the deallocation code in the xhci driver, so that usb_add_hcd()/usb_remove_hcd() can be called repeatedly without crashing. In case of DRD mode, the DRD library calls /usb_remove_hcd() while switching from HOST mode to Device mode, but it doesnot call usb_put_hcd(). We need to preserve the already allocated xhci struct for the subsequent call of usb_add_hcd() from the DRD library. A new quirk flag XHCI_DRD_SUPPORT is added to differentiate between normal usb_remove_hcd and drd specific call. Signed-off-by: George Cherian --- drivers/usb/host/xhci.c | 22 -- drivers/usb/host/xhci.h | 1 + 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 2a5d45b..d4196f8 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -666,7 +666,8 @@ static void xhci_only_stop_hcd(struct usb_hcd *hcd) * calls this function when allocation fails in usb_add_hcd(), or * usb_remove_hcd() is called). So we need to unset xHCI's pointer. */ - xhci->shared_hcd = NULL; + if (!(xhci->quirks & XHCI_DRD_SUPPORT)) + xhci->shared_hcd = NULL; spin_unlock_irq(&xhci->lock); } @@ -4815,6 +4816,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) struct xhci_hcd *xhci; struct device *dev = hcd->self.controller; int retval; + boolallocated = false; /* Accept arbitrarily long scatter-gather lists */ hcd->self.sg_tablesize = ~0; @@ -4826,10 +4828,15 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) hcd->self.no_stop_on_short = 1; if (usb_hcd_is_primary_hcd(hcd)) { - xhci = kzalloc(sizeof(struct xhci_hcd), GFP_KERNEL); - if (!xhci) - return -ENOMEM; - *((struct xhci_hcd **) hcd->hcd_priv) = xhci; + if (*((struct xhci_hcd **)hcd->hcd_priv) == NULL) { + xhci = kzalloc(sizeof(struct xhci_hcd), GFP_KERNEL); + if (!xhci) + return -ENOMEM; + *((struct xhci_hcd **)hcd->hcd_priv) = xhci; + allocated = true; + } else { + xhci = *((struct xhci_hcd **)hcd->hcd_priv); + } xhci->main_hcd = hcd; /* Mark the first roothub as being USB 2.0. * The xHCI driver will register the USB 3.0 roothub. @@ -4902,7 +4909,10 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) xhci_dbg(xhci, "Called HCD init\n"); return 0; error: - kfree(xhci); + if (allocated) { + *((struct xhci_hcd **)hcd->hcd_priv) = NULL; + kfree(xhci); + } return retval; } EXPORT_SYMBOL_GPL(xhci_gen_setup); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index df76d64..2248058 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1560,6 +1560,7 @@ struct xhci_hcd { #define XHCI_SPURIOUS_WAKEUP (1 << 18) /* For controllers with a broken beyond repair streams implementation */ #define XHCI_BROKEN_STREAMS(1 << 19) +#define XHCI_DRD_SUPPORT (1 << 20) unsigned intnum_active_eps; unsigned intlimit_active_eps; /* There are two roothubs to keep track of bus suspend info for */ -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 03/19] usb: host: xhci-plat: Add support to pass XHCI_DRD_SUPPORT quirk
Extend the platform data to pass XHCI_DRD_SUPPORT quirk to the xhci driver. Signed-off-by: George Cherian --- drivers/usb/host/xhci-plat.c | 4 include/linux/usb/xhci_pdriver.h | 1 + 2 files changed, 5 insertions(+) diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 3d78b0c..2c42273 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -27,6 +27,10 @@ static struct hc_driver __read_mostly xhci_plat_hc_driver; static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci) { + struct usb_xhci_pdata *pdata = dev_get_platdata(dev); + + if (pdata->usb_drd_support) + xhci->quirks |= XHCI_DRD_SUPPORT; /* * As of now platform drivers don't provide MSI support so we ensure * here that the generic code does not try to make a pci_dev from our diff --git a/include/linux/usb/xhci_pdriver.h b/include/linux/usb/xhci_pdriver.h index 376654b..539c2d8 100644 --- a/include/linux/usb/xhci_pdriver.h +++ b/include/linux/usb/xhci_pdriver.h @@ -22,6 +22,7 @@ */ struct usb_xhci_pdata { unsignedusb3_lpm_capable:1; + unsignedusb_drd_support:1; }; #endif /* __USB_CORE_XHCI_PDRIVER_H */ -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 01/19] usb: common: drd-lib: Add DRD lib for USB.
Add USB DRD library. This Library facilitates to switch roles between HOST and Device modes. A DRD should be added to the library using usb_drd_add(). Register the HOST and UDC using usb_drd_register_hcd/udc(). Un-Register the HOST and UDC using usb_drd_unregister_hcd/udc(). Depending on the state of IP - Call the following to start/stop HOST controller usb_drd_start/stop_hcd(). This internally calls usb_add/remove_hcd() or IP specific low level start/stop defined in ll_start/stop Call the following to start/stop UDC usb_drd_start/stop_udc(). This internally calls udc_start/udc_stop() or IP specific low level start/stop defined in ll_start/stop Signed-off-by: George Cherian --- drivers/usb/Kconfig | 15 ++ drivers/usb/common/Makefile | 1 + drivers/usb/common/drd-lib.c | 346 +++ include/linux/usb/drd.h | 77 ++ 4 files changed, 439 insertions(+) create mode 100644 drivers/usb/common/drd-lib.c create mode 100644 include/linux/usb/drd.h diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index ae481c3..ea0d944 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -34,6 +34,21 @@ config USB_COMMON default y depends on USB || USB_GADGET +config DRD_LIB + tristate "DRD Library support" + default y + depends on USB && USB_GADGET + ---help--- + This option adds DRD Library support for Universal Serial Bus (USB). + DRD Library faciliatets the Role switching by HOST and DEVICE roles, + If your hardware has a Dual Role Device. + + The DRD Library uses USB core API's to start/stop HOST controllers, + UDC API's to start/stop DEVICE controllers, ther by enabling to + switch roles between HOST and Device modes. + + Say N if unsure. + config USB_ARCH_HAS_HCD def_bool y diff --git a/drivers/usb/common/Makefile b/drivers/usb/common/Makefile index ca2f8bd..e2c1593 100644 --- a/drivers/usb/common/Makefile +++ b/drivers/usb/common/Makefile @@ -7,3 +7,4 @@ usb-common-y += common.o usb-common-$(CONFIG_USB_LED_TRIG) += led.o obj-$(CONFIG_USB_OTG_FSM) += usb-otg-fsm.o +obj-$(CONFIG_DRD_LIB) += drd-lib.o diff --git a/drivers/usb/common/drd-lib.c b/drivers/usb/common/drd-lib.c new file mode 100644 index 000..6159436 --- /dev/null +++ b/drivers/usb/common/drd-lib.c @@ -0,0 +1,346 @@ +/** + * drd-lib.c - USB DRD library functions + * + * Copyright (C) 2014 Texas Instruments + * Author: George Cherian + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/** + * struct usb_drd - describes one dual role device + * @host - the HOST controller device of this drd + * @gadget - the gadget of drd + * @parent - the device to the actual controller + * @list - for use by the drd lib + * @state - specifies the current state + * + * This represents the internal data structure which is used by the UDC-class + * to hold information about udc driver and gadget together. + */ +struct usb_drd { + struct usb_drd_host *host; + struct usb_drd_gadget *gadget; + struct device *parent; + struct list_headlist; + unsigned intstate; +}; + +static LIST_HEAD(drd_list); +static DEFINE_SPINLOCK(drd_lock); + +static struct usb_drd *usb_drd_get_dev(struct device *parent) +{ + struct usb_drd *drd; + + spin_lock(&drd_lock); + list_for_each_entry(drd, &drd_list, list) + if (drd->parent == parent) + goto out; + drd = NULL; +out: + spin_unlock(&drd_lock); + + return drd; +} + +int usb_drd_get_state(struct device *parent) +{ + struct usb_drd *drd; + + drd = usb_drd_get_dev(parent); + if (!drd) + return -ENODEV; + + return drd->state; +} +EXPORT_SYMBOL_GPL(usb_drd_get_state); + +int usb_drd_release(struct device *parent) +{ + struct usb_drd *drd; + int ret; + + spin_lock(&drd_lock); + list_for_each_entry(drd, &drd_list, list) { + if (drd->parent == parent) { + kfree(drd); + ret = 0; + goto out; + } + } + ret = -ENO
[PATCH 05/19] usb: host: xhci-plat: Add support to pass XHCI_NEEDS_LHC_RESET quirk
Extend the platform data to pass XHCI_NEEDS_LHC_RESET quirk to the xhci driver. Signed-off-by: George Cherian --- drivers/usb/host/xhci-plat.c | 3 +++ include/linux/usb/xhci_pdriver.h | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 2c42273..d8d024d 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -31,6 +31,9 @@ static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci) if (pdata->usb_drd_support) xhci->quirks |= XHCI_DRD_SUPPORT; + + if (pdata->usb_needs_lhc_reset) + xhci->quirks |= XHCI_NEEDS_LHC_RESET; /* * As of now platform drivers don't provide MSI support so we ensure * here that the generic code does not try to make a pci_dev from our diff --git a/include/linux/usb/xhci_pdriver.h b/include/linux/usb/xhci_pdriver.h index 539c2d8..8ef7321 100644 --- a/include/linux/usb/xhci_pdriver.h +++ b/include/linux/usb/xhci_pdriver.h @@ -23,6 +23,7 @@ struct usb_xhci_pdata { unsignedusb3_lpm_capable:1; unsignedusb_drd_support:1; + unsignedusb_needs_lhc_reset:1; }; #endif /* __USB_CORE_XHCI_PDRIVER_H */ -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 07/19] usb: host: xhci: Adapt xhci to use usb drd library
Adapt the xhci-plat driver to use drd library functions. In prepration to support DRD on dwc3. Signed-off-by: George Cherian --- drivers/usb/host/xhci-plat.c | 15 +++ 1 file changed, 15 insertions(+) diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index d8d024d..fbbbd59 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include "xhci.h" @@ -78,6 +80,7 @@ static int xhci_plat_probe(struct platform_device *pdev) struct resource *res; struct usb_hcd *hcd; struct clk *clk; + struct usb_drd_host *drd_host; int ret; int irq; @@ -169,6 +172,17 @@ static int xhci_plat_probe(struct platform_device *pdev) if (ret) goto put_usb3_hcd; + drd_host = kzalloc(sizeof(*drd_host), GFP_KERNEL); + if (!drd_host) + return -ENOMEM; + + drd_host->main_hcd = xhci->main_hcd; + drd_host->shared_hcd = xhci->shared_hcd; + drd_host->hcd_irq = irq; + drd_host->host_setup = NULL; + + usb_drd_register_hcd(pdev->dev.parent, drd_host); + return 0; put_usb3_hcd: @@ -200,6 +214,7 @@ static int xhci_plat_remove(struct platform_device *dev) if (!IS_ERR(clk)) clk_disable_unprepare(clk); usb_put_hcd(hcd); + usb_drd_unregister_hcd(dev->dev.parent); kfree(xhci); return 0; -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 06/19] usb: dwc3: host: Pass the XHCI_DRD_SUPPORT and XHCI_NEEDS_LHC_RESET quirk
Pass the quir flag XHCI_DRD_SUPPORT from DWC3 host to xhci platform driver. This enables xhci driver to handle deallocation's differently while in DRD mode. Pass the quirk flag XHCI_NEEDS_LHC_RESET from DWC3 host to xhci platform driver. This enables to do LHRESET during xhci_reset(). Signed-off-by: George Cherian --- drivers/usb/dwc3/host.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c index dcb8ca0..257b5b5 100644 --- a/drivers/usb/dwc3/host.c +++ b/drivers/usb/dwc3/host.c @@ -53,6 +53,8 @@ int dwc3_host_init(struct dwc3 *dwc) #ifdef CONFIG_DWC3_HOST_USB3_LPM_ENABLE pdata.usb3_lpm_capable = 1; #endif + pdata.usb_drd_support = 1; + pdata.usb_needs_lhc_reset = 1; ret = platform_device_add_data(xhci, &pdata, sizeof(pdata)); if (ret) { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 09/19] usb: dwc3: dwc3-omap: Make the wrapper interrupt shared
OTG interrupt and wrapper is shared Signed-off-by: George Cherian --- drivers/usb/dwc3/dwc3-omap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 172d64e..f99e2ca 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -525,8 +525,8 @@ static int dwc3_omap_probe(struct platform_device *pdev) reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG); omap->dma_status = !!(reg & USBOTGSS_SYSCONFIG_DMADISABLE); - ret = devm_request_irq(dev, omap->irq, dwc3_omap_interrupt, 0, - "dwc3-omap", omap); + ret = devm_request_irq(dev, omap->irq, dwc3_omap_interrupt, IRQF_SHARED, + "dwc3-omap", omap); if (ret) { dev_err(dev, "failed to request IRQ #%d --> %d\n", omap->irq, ret); -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 08/19] usb: dwc3: core: Add dwc3_drd_helper function
This helper function, facilitates to re-initialize the event buffers. It re-initilizes the event buffers while switching role from HOST to DEVICE mode. The DWC3 IP shares internal RAM for both HOST and Device specific registers. So while switching roles from HOST to Device modes, it's required to re-initialize the EVENT buffer registers for the Device mode to continue work properly. dwc3_event_buffers_setup() is exported out from core.c via wrapper dwc3_core_gadget_helper() which will be invoked from dwc3 otg driver. Signed-off-by: George Cherian --- drivers/usb/dwc3/core.c | 5 + drivers/usb/dwc3/core.h | 1 + 2 files changed, 6 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 25ddc39..fadd767 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -254,6 +254,11 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) } } +int dwc3_core_gadget_helper(struct dwc3 *dwc) +{ + return dwc3_event_buffers_setup(dwc); +} + static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc) { if (!dwc->has_hibernation) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 4bb9aa6..6b38223 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -981,6 +981,7 @@ struct dwc3_gadget_ep_cmd_params { /* prototypes */ void dwc3_set_mode(struct dwc3 *dwc, u32 mode); int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc); +int dwc3_core_gadget_helper(struct dwc3 *dwc); #if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) int dwc3_host_init(struct dwc3 *dwc); -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 04/19] usb: host xhci: Add XHCI_NEEDS_LHC_RESET quirk
This adds XHCI_NEEDS_LHC_RESET quirk, to make sure only Light Host Reset is done during xhci_reset(). This is mainly useful when we switch roles HOST to Device mode and viceversa. The DWC3 IP shares internal RAM for both HOST and Device specific registers. So while switching roles between HOST and Device modes, it's advbised to do a LIGHT HC reset else the already configured global registers of the DWC3 IP gets re-initialized. Signed-off-by: George Cherian --- drivers/usb/host/xhci.c | 5 +++-- drivers/usb/host/xhci.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index d4196f8..5dabf9a 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -170,11 +170,12 @@ int xhci_reset(struct xhci_hcd *xhci) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "// Reset the HC"); command = readl(&xhci->op_regs->command); - command |= CMD_RESET; + command |= (xhci->quirks & XHCI_NEEDS_LHC_RESET) ? CMD_LRESET : CMD_RESET; writel(command, &xhci->op_regs->command); ret = xhci_handshake(xhci, &xhci->op_regs->command, - CMD_RESET, 0, 10 * 1000 * 1000); + (xhci->quirks & XHCI_NEEDS_LHC_RESET) ? CMD_LRESET : CMD_RESET, + 0, 10 * 1000 * 1000); if (ret) return ret; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 2248058..1b14b09 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1561,6 +1561,7 @@ struct xhci_hcd { /* For controllers with a broken beyond repair streams implementation */ #define XHCI_BROKEN_STREAMS(1 << 19) #define XHCI_DRD_SUPPORT (1 << 20) +#define XHCI_NEEDS_LHC_RESET (1 << 21) unsigned intnum_active_eps; unsigned intlimit_active_eps; /* There are two roothubs to keep track of bus suspend info for */ -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 10/19] usb: dwc3: core: Adapt to named interrupts
From: Felipe Balbi Add support to use interrupt names, Following are the interrupt names Peripheral Interrupt - peripheral HOST Interrupt - host OTG Interrupt - otg Signed-off-by: Felipe Balbi Signed-off-by: George Cherian --- drivers/usb/dwc3/core.c | 12 drivers/usb/dwc3/core.h | 7 +++ 2 files changed, 19 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index fadd767..dbd5589 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -760,6 +760,18 @@ static int dwc3_probe(struct platform_device *pdev) dwc->xhci_resources[1].flags = res->flags; dwc->xhci_resources[1].name = res->name; + dwc->otg_irq = platform_get_irq_byname(pdev, "otg"); + if (!dwc->otg_irq) + dev_err(dev, "missing OTG IRQ\n"); + + dwc->gadget_irq = platform_get_irq_byname(pdev, "peripheral"); + if (!dwc->gadget_irq) + dev_err(dev, "missing peripheral IRQ\n"); + + dwc->xhci_irq = platform_get_irq_byname(pdev, "host"); + if (!dwc->xhci_irq) + dev_err(dev, "missing HOST IRQ\n"); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "missing memory resource\n"); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 6b38223..7c5ae37 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -651,6 +651,9 @@ struct dwc3_scratchpad_array { * @maximum_speed: maximum speed requested (mainly for testing purposes) * @revision: revision register contents * @dr_mode: requested mode of operation + * @xhci_irq: IRQ number for XHCI IRQs + * @gadget_irq: IRQ number for Peripheral IRQs + * @otg_irq: IRQ number for OTG IRQs * @usb2_phy: pointer to USB2 PHY * @usb3_phy: pointer to USB3 PHY * @usb2_generic_phy: pointer to USB2 PHY @@ -747,6 +750,10 @@ struct dwc3 { enum usb_dr_modedr_mode; + int gadget_irq; + int xhci_irq; + int otg_irq; + /* used for suspend/resume */ u32 dcfg; u32 gctl; -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 16/19] arm: dts: omap5: Add named interrupt property for dwc3
Add interrupt names so that the same can be used for OTG easily. Signed-off-by: George Cherian --- arch/arm/boot/dts/omap5.dtsi | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi index 256b7f6..a712ad9 100644 --- a/arch/arm/boot/dts/omap5.dtsi +++ b/arch/arm/boot/dts/omap5.dtsi @@ -817,7 +817,12 @@ dwc3@4a03 { compatible = "snps,dwc3"; reg = <0x4a03 0x1>; - interrupts = ; + interrupts = , +, +; + interrupt-names = "peripheral", + "host", + "otg"; phys = <&usb2_phy>, <&usb3_phy>; phy-names = "usb2-phy", "usb3-phy"; dr_mode = "peripheral"; -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 12/19] usb: dwc3: gadget: Adapt gadget to drd library
Adapt the dwc3 gadget to use drd library functions. In prepration to support DRD on dwc3. Signed-off-by: George Cherian --- drivers/usb/dwc3/gadget.c | 128 -- 1 file changed, 100 insertions(+), 28 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 2c54d45..a75fae5 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -29,6 +29,7 @@ #include #include +#include #include "debug.h" #include "core.h" @@ -2681,6 +2682,89 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc) return ret; } +void dwc3_gadget_release(struct device *dev) +{ + struct usb_gadget *gadget = container_of(dev, struct usb_gadget, dev); + struct dwc3_gadget *dwc_gadget = gadget_to_dwc_gadget(gadget); + struct dwc3 *dwc = dwc_gadget->dwc; + + dev_dbg(dev, "releasing '%s'\n", dev_name(dev)); + dwc3_gadget_free_endpoints(dwc); + dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE, + dwc->ep0_bounce, dwc->ep0_bounce_addr); + kfree(dwc->setup_buf); + dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb), + dwc->ep0_trb, dwc->ep0_trb_addr); + dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req), + dwc->ctrl_req, dwc->ctrl_req_addr); + usb_drd_unregister_udc(dwc->dev); + kfree(dwc_gadget); +} + +int dwc3_gadget_setup(void *data) +{ + struct dwc3 *dwc = data; + struct dwc3_gadget *dwc_gadget; + struct usb_drd_gadget *drd_gadget; + struct usb_drd_setup *gadget_setup; + int ret; + + drd_gadget = kzalloc(sizeof(*drd_gadget), GFP_KERNEL); + if (!drd_gadget) { + ret = -ENOMEM; + goto err1; + } + + gadget_setup = kzalloc(sizeof(*gadget_setup), GFP_KERNEL); + if (!gadget_setup) { + ret = -ENOMEM; + goto err2; + } + + dwc_gadget = kzalloc(sizeof(*dwc_gadget), GFP_KERNEL); + if (!dwc_gadget) { + ret = -ENOMEM; + goto err3; + } + + drd_gadget->g_driver = dwc->gadget_driver; + + /* +* Pass the DWC3 specific routines for +* switching roles to the drd library +*/ + gadget_setup->ll_start = NULL; + gadget_setup->ll_stop = NULL; + gadget_setup->ll_release = dwc3_gadget_release; + gadget_setup->data = (void *)dwc; + drd_gadget->gadget_setup = gadget_setup; + + dwc_gadget->gadget.ops = &dwc3_gadget_ops; + dwc_gadget->gadget.max_speed= USB_SPEED_SUPER; + dwc_gadget->gadget.speed= USB_SPEED_UNKNOWN; + dwc_gadget->gadget.sg_supported = true; + dwc_gadget->gadget.name = "dwc3-gadget"; + dwc_gadget->dwc = dwc; + drd_gadget->gadget = &dwc_gadget->gadget; + + /* +* Per databook, DWC3 needs buffer size to be aligned to MaxPacketSize +* on ep out. +*/ + dwc_gadget->gadget.quirk_ep_out_aligned_size = true; + dwc->dwc_gadget = dwc_gadget; + usb_drd_register_udc(dwc->dev, drd_gadget); + + return 0; + +err3: + kfree(gadget_setup); +err2: + kfree(drd_gadget); +err1: + return ret; +} + /** * dwc3_gadget_init - Initializes gadget related registers * @dwc: pointer to our controller context structure @@ -2690,7 +2774,6 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc) int dwc3_gadget_init(struct dwc3 *dwc) { int ret; - struct dwc3_gadget *dwc_gadget; dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req), &dwc->ctrl_req_addr, GFP_KERNEL); @@ -2723,24 +2806,9 @@ int dwc3_gadget_init(struct dwc3 *dwc) goto err3; } - dwc_gadget = kzalloc(sizeof(*dwc_gadget), GFP_KERNEL); - if (!dwc_gadget) { - ret = -ENOMEM; + ret = dwc3_gadget_setup(dwc); + if (ret) goto err3; - } - - dwc_gadget->gadget.ops = &dwc3_gadget_ops; - dwc_gadget->gadget.max_speed= USB_SPEED_SUPER; - dwc_gadget->gadget.speed= USB_SPEED_UNKNOWN; - dwc_gadget->gadget.sg_supported = true; - dwc_gadget->gadget.name = "dwc3-gadget"; - dwc_gadget->dwc = dwc; - - /* -* Per databook, DWC3 needs buffer size to be aligned to MaxPacketSize -* on ep out. -*/ - dwc_gadget->gadget.quirk_ep_out_aligned_size = true; /* * REVISIT: Here we should clear all pending IRQs to be @@ -2751,7 +2819,8 @@
[PATCH 14/19] usb: dwc3: otg: Add the initial otg driver for dwc3.
Add the Initial OTG driver for dwc3. Currently support only * ID based Role switching. Signed-off-by: George Cherian --- drivers/usb/dwc3/Makefile | 4 ++ drivers/usb/dwc3/core.c | 10 +--- drivers/usb/dwc3/core.h | 10 drivers/usb/dwc3/otg.c| 126 ++ 4 files changed, 142 insertions(+), 8 deletions(-) create mode 100644 drivers/usb/dwc3/otg.c diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index bb34fbc..fe7af97 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -12,6 +12,10 @@ ifneq ($(filter y,$(CONFIG_USB_DWC3_HOST) $(CONFIG_USB_DWC3_DUAL_ROLE)),) dwc3-y += host.o endif +ifneq ($(CONFIG_USB_DWC3_DUAL_ROLE),) + dwc3-y += otg.o +endif + ifneq ($(filter y,$(CONFIG_USB_DWC3_GADGET) $(CONFIG_USB_DWC3_DUAL_ROLE)),) dwc3-y += gadget.o ep0.o endif diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index dbd5589..dd4af3f 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -685,15 +685,9 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) break; case USB_DR_MODE_OTG: dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); - ret = dwc3_host_init(dwc); - if (ret) { - dev_err(dev, "failed to initialize host\n"); - return ret; - } - - ret = dwc3_gadget_init(dwc); + ret = dwc3_otg_init(dwc); if (ret) { - dev_err(dev, "failed to initialize gadget\n"); + dev_err(dev, "failed to initialize otg\n"); return ret; } break; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index eb2e970..001d77d 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1103,6 +1103,16 @@ static inline int dwc3_send_gadget_generic_command(struct dwc3 *dwc, { return 0; } #endif +#if IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) +int dwc3_otg_init(struct dwc3 *dwc); +void dwc3_otg_exit(struct dwc3 *dwc); +#else +static inline int dwc3_otg_init(struct dwc3 *dwc) +{ return 0; } +static inline void dwc3_otg_exit(struct dwc3 *dwc) +{ } +#endif + /* power management interface */ #if !IS_ENABLED(CONFIG_USB_DWC3_HOST) int dwc3_gadget_suspend(struct dwc3 *dwc); diff --git a/drivers/usb/dwc3/otg.c b/drivers/usb/dwc3/otg.c new file mode 100644 index 000..b5c31c0 --- /dev/null +++ b/drivers/usb/dwc3/otg.c @@ -0,0 +1,126 @@ +/** + * otg.c - DesignWare USB3 DRD Controller OTG + * + * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com + * + * Authors: George Cherian + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include "core.h" +#include "io.h" + +#define DWC3_GSTS_OTG_IP (1 << 10) + +static irqreturn_t dwc3_otg_interrupt(int irq , void *_dwc) +{ + struct dwc3 *dwc = _dwc; + u32 reg; + + spin_lock(&dwc->lock); + reg = dwc3_readl(dwc->regs, DWC3_GSTS); + if (reg & DWC3_GSTS_OTG_IP) { + reg = dwc3_readl(dwc->regs, DWC3_OEVT); + dev_vdbg(dwc->dev, "OTG Interrupt %x\n", reg); + dwc3_writel(dwc->regs, DWC3_OEVT, reg); + spin_unlock(&dwc->lock); + return IRQ_WAKE_THREAD; + } + + spin_unlock(&dwc->lock); + return IRQ_NONE; +} + +static irqreturn_t dwc3_otg_thread_interrupt(int irq, void *_dwc) +{ + struct dwc3 *dwc = _dwc; + u32 reg = dwc3_readl(dwc->regs, DWC3_OSTS); + + dev_vdbg(dwc->dev, "OTG thread interrupt\n"); + if ((reg & DWC3_OSTS_CONIDSTS)) { + usb_drd_stop_hcd(dwc->dev); + dwc3_writel(dwc->regs, DWC3_OCFG, DWC3_OCFG_SFTRSTMASK); + dwc3_writel(dwc->regs, DWC3_OCTL, + DWC3_OCTL_SESREQ | DWC3_OCTL_PERIMODE); + if (usb_drd_get_state(dwc->dev) & DRD_DEVICE_REGISTERED) { + usb_drd_start_udc(dwc->dev); + } else { + dwc3_core_gadget_helper(dwc); + dwc3_gadget_init(dwc); + } + dwc3_writel(dwc->regs, DWC3_OEVTEN, + DWC3_OEVTEN_CON
[PATCH 11/19] usb: dwc3: Add seperate dwc3_gadget object to support gadget release
With the current implementation it's impossible to release the gadget. Add a separate dwc3_gadget object to dwc3 structure so that the same can be freed during the gadget release. This is in prepration to adapt dwc3 gadget driver to drd library. DRD library uses usb_del/add_gadget_udc while switching roles between HOST and DEVICE modes. If the usb_gadget is not released during usb_del_gadget_udc, the subsequent usb_add_gadget_udc would try to initialize an already initialized kobject. To avoid this make sure we have an easily freeable object. Signed-off-by: George Cherian --- drivers/usb/dwc3/core.h | 7 ++- drivers/usb/dwc3/ep0.c| 35 -- drivers/usb/dwc3/gadget.c | 113 ++ drivers/usb/dwc3/gadget.h | 1 + 4 files changed, 101 insertions(+), 55 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 7c5ae37..7fbe736 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -626,6 +626,11 @@ struct dwc3_scratchpad_array { __le64 dma_adr[DWC3_MAX_HIBER_SCRATCHBUFS]; }; +struct dwc3_gadget { + struct usb_gadget gadget; + struct dwc3 *dwc; +}; + /** * struct dwc3 - representation of our controller * @ctrl_req: usb control request which is used for ep0 @@ -736,7 +741,7 @@ struct dwc3 { struct dwc3_event_buffer **ev_buffs; struct dwc3_ep *eps[DWC3_ENDPOINTS_NUM]; - struct usb_gadget gadget; + struct dwc3_gadget *dwc_gadget; struct usb_gadget_driver *gadget_driver; struct usb_phy *usb2_phy; diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index baeedbd..e7409f1 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -109,6 +109,7 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, struct dwc3_request *req) { struct dwc3 *dwc = dep->dwc; + struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget; req->request.actual = 0; req->request.status = -EINPROGRESS; @@ -152,7 +153,7 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, direction = !dwc->ep0_expect_in; dwc->delayed_status = false; - usb_gadget_set_state(&dwc->gadget, USB_STATE_CONFIGURED); + usb_gadget_set_state(&dwc_gadget->gadget, USB_STATE_CONFIGURED); if (dwc->ep0state == EP0_STATUS_PHASE) __dwc3_ep0_do_control_status(dwc, dwc->eps[direction]); @@ -391,6 +392,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl, int set) { struct dwc3_ep *dep; + struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget; u32 recip; u32 wValue; u32 wIndex; @@ -401,7 +403,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, wValue = le16_to_cpu(ctrl->wValue); wIndex = le16_to_cpu(ctrl->wIndex); recip = ctrl->bRequestType & USB_RECIP_MASK; - state = dwc->gadget.state; + state = dwc_gadget->gadget.state; switch (recip) { case USB_RECIP_DEVICE: @@ -499,7 +501,8 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { - enum usb_device_state state = dwc->gadget.state; + struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget; + enum usb_device_state state = dwc_gadget->gadget.state; u32 addr; u32 reg; @@ -521,26 +524,28 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) dwc3_writel(dwc->regs, DWC3_DCFG, reg); if (addr) - usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS); + usb_gadget_set_state(&dwc_gadget->gadget, USB_STATE_ADDRESS); else - usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT); + usb_gadget_set_state(&dwc_gadget->gadget, USB_STATE_DEFAULT); return 0; } static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { + struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget; int ret; spin_unlock(&dwc->lock); - ret = dwc->gadget_driver->setup(&dwc->gadget, ctrl); + ret = dwc->gadget_driver->setup(&dwc_gadget->gadget, ctrl); spin_lock(&dwc->lock); return ret; } static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { - enum usb_device_state state = dwc->gadget.state; + struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget; + enum usb_device_state state = dwc_gadget->gadget.state; u32 cfg; int ret; u32 reg; @
[PATCH 13/19] usb: dwc3: core: Add DWC3 OTG specific register defines
Add OTG reggister defines to DWC3 core.h Signed-off-by: George Cherian --- drivers/usb/dwc3/core.h | 68 + 1 file changed, 68 insertions(+) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 7fbe736..eb2e970 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -381,6 +381,74 @@ #define DWC3_DEPCMD_TYPE_BULK 2 #define DWC3_DEPCMD_TYPE_INTR 3 +/* OTG Configuration Register */ +#define DWC3_OCFG_DISPWRCUTTOFF(1 << 5) +#define DWC3_OCFG_HIBDISMASK (1 << 4) +#define DWC3_OCFG_SFTRSTMASK (1 << 3) +#define DWC3_OCFG_OTGVERSION (1 << 2) +#define DWC3_OCFG_HNPCAP (1 << 1) +#define DWC3_OCFG_SRPCAP (1 << 0) + +/* OTG CTL Register */ +#define DWC3_OCTL_OTG3GOERR(1 << 7) +#define DWC3_OCTL_PERIMODE (1 << 6) +#define DWC3_OCTL_PRTPWRCTL(1 << 5) +#define DWC3_OCTL_HNPREQ (1 << 4) +#define DWC3_OCTL_SESREQ (1 << 3) +#define DWC3_OCTL_TERMSELIDPULSE (1 << 2) +#define DWC3_OCTL_DEVSETHNPEN (1 << 1) +#define DWC3_OCTL_HOSTSETHNPEN (1 << 0) + +/* OTG Event Register */ +#define DWC3_OEVT_DEVICEMODE (1 << 31) +#define DWC3_OEVT_XHCIRUNSTPSET(1 << 27) +#define DWC3_OEVT_DEVRUNSTPSET (1 << 26) +#define DWC3_OEVT_HIBENTRY (1 << 25) +#define DWC3_OEVT_IDSTSCHNG(1 << 24) +#define DWC3_OEVT_HRRCONFNOTIF (1 << 23) +#define DWC3_OEVT_HRRINITNOTIF (1 << 22) +#define DWC3_OEVT_ADEVIDLE (1 << 21) +#define DWC3_OEVT_ADEVBHOSTEND (1 << 20) +#define DWC3_OEVT_ADEVHOST (1 << 19) +#define DWC3_OEVT_ADEVHNPCHNG (1 << 18) +#define DWC3_OEVT_ADEVSRPDET (1 << 17) +#define DWC3_OEVT_ADEVSESSENDDET (1 << 16) +#define DWC3_OEVT_BDEVBHOSTEND (1 << 11) +#define DWC3_OEVT_BDEVHNPCHNG (1 << 10) +#define DWC3_OEVT_BDEVSESSVLDDET (1 << 9) +#define DWC3_OEVT_BDEVVBUSCHNG (1 << 8) +#define DWC3_OEVT_BSESSVLD (1 << 3) +#define DWC3_OEVT_HOSTNEGSTS (1 << 2) +#define DWC3_OEVT_SESSREQSTS (1 << 1) +#define DWC3_OEVT_ERR (1 << 0) + +/* OTG Event Enable Register */ +#define DWC3_OEVTEN_XHCIRUNSTPSETEN(1 << 27) +#define DWC3_OEVTEN_DEVRUNSTPSETEN (1 << 26) +#define DWC3_OEVTEN_HIBENTRYEN (1 << 25) +#define DWC3_OEVTEN_CONIDSTSCHNGEN (1 << 24) +#define DWC3_OEVTEN_HRRCONFNOTIFEN (1 << 23) +#define DWC3_OEVTEN_HRRINITNOTIFEN (1 << 22) +#define DWC3_OEVTEN_ADEVIDLEEN (1 << 21) +#define DWC3_OEVTEN_ADEVBHOSTENDEN (1 << 20) +#define DWC3_OEVTEN_ADEVHOSTEN (1 << 19) +#define DWC3_OEVTEN_ADEVHNPCHNGEN (1 << 18) +#define DWC3_OEVTEN_ADEVSRPDETEN (1 << 17) +#define DWC3_OEVTEN_ADEVSESSENDDETEN (1 << 16) +#define DWC3_OEVTEN_BDEVHOSTENDEN (1 << 11) +#define DWC3_OEVTEN_BDEVHNPCHNGEN (1 << 10) +#define DWC3_OEVTEN_BDEVSESSVLDDETEN (1 << 9) +#define DWC3_OEVTEN_BDEVVBUSCHNGEVNTEN (1 << 8) + +/* OTG Status Register */ +#define DWC3_OSTS_DEVRUNSTP(1 << 13) +#define DWC3_OSTS_XHCIRUNSTP (1 << 12) +#define DWC3_OSTS_PERIPHERALSTATE (1 << 4) +#define DWC3_OSTS_XHCIPORTPOWER(1 << 3) +#define DWC3_OSTS_BSESVLD (1 << 2) +#define DWC3_OSTS_VBUSVLD (1 << 1) +#define DWC3_OSTS_CONIDSTS (1 << 0) + /* Structures */ struct dwc3_trb; -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 15/19] arm: dts: am4372: Add named interrupt property for dwc3
From: Felipe Balbi Add interrupt names so that the same can be used for OTG easily. Signed-off-by: Felipe Balbi Signed-off-by: George Cherian --- arch/arm/boot/dts/am4372.dtsi | 18 ++ 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi index e19068d..3dda4c8 100644 --- a/arch/arm/boot/dts/am4372.dtsi +++ b/arch/arm/boot/dts/am4372.dtsi @@ -810,8 +810,13 @@ usb1: usb@4839 { compatible = "synopsys,dwc3"; - reg = <0x4839 0x1>; - interrupts = ; + reg = <0x4839 0x17000>; + interrupts = , +, +; + interrupt-names = "peripheral", + "host", + "otg"; phys = <&usb2_phy1>; phy-names = "usb2-phy"; maximum-speed = "high-speed"; @@ -834,8 +839,13 @@ usb2: usb@483d { compatible = "synopsys,dwc3"; - reg = <0x483d 0x1>; - interrupts = ; + reg = <0x483d 0x17000>; + interrupts = , +, +; + interrupt-names = "peripheral", + "host", + "otg"; phys = <&usb2_phy2>; phy-names = "usb2-phy"; maximum-speed = "high-speed"; -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 18/19] arm: dts: exynos5250: Add named interrupt property for dwc3
Add interrupt names so that the same can be used for OTG easily. Signed-off-by: George Cherian --- arch/arm/boot/dts/exynos5250.dtsi | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi index f21b9aa..c74cd8b 100644 --- a/arch/arm/boot/dts/exynos5250.dtsi +++ b/arch/arm/boot/dts/exynos5250.dtsi @@ -558,7 +558,12 @@ dwc3 { compatible = "synopsys,dwc3"; reg = <0x1200 0x1>; - interrupts = <0 72 0>; + interrupts = <0 72 0>, +<0 72 0>, +<0 72 0>; + interrupt-names = "peripheral", + "host", + "otg"; phys = <&usbdrd_phy 0>, <&usbdrd_phy 1>; phy-names = "usb2-phy", "usb3-phy"; }; -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 17/19] arm: dts: dra7: Add named interrupt property for dwc3
Add interrupt names so that the same can be used for OTG easily. Signed-off-by: George Cherian --- arch/arm/boot/dts/dra7.dtsi | 28 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index 9cc9843..78f1761 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -1153,7 +1153,12 @@ usb1: usb@4889 { compatible = "snps,dwc3"; reg = <0x4889 0x17000>; - interrupts = ; + interrupts = , +, +; + interrupt-names = "peripheral", + "host", + "otg"; phys = <&usb2_phy1>, <&usb3_phy1>; phy-names = "usb2-phy", "usb3-phy"; tx-fifo-resize; @@ -1174,7 +1179,12 @@ usb2: usb@488d { compatible = "snps,dwc3"; reg = <0x488d 0x17000>; - interrupts = ; + interrupts = , +, +; + interrupt-names = "peripheral", + "host", + "otg"; phys = <&usb2_phy2>; phy-names = "usb2-phy"; tx-fifo-resize; @@ -1197,7 +1207,12 @@ usb3: usb@4891 { compatible = "snps,dwc3"; reg = <0x4891 0x17000>; - interrupts = ; + interrupts = , +, +; + interrupt-names = "peripheral", + "host", + "otg"; tx-fifo-resize; maximum-speed = "high-speed"; dr_mode = "otg"; @@ -1217,7 +1232,12 @@ usb4: usb@4895 { compatible = "snps,dwc3"; reg = <0x4895 0x17000>; - interrupts = ; + interrupts = , +, +; + interrupt-names = "peripheral", + "host", + "otg"; tx-fifo-resize; maximum-speed = "high-speed"; dr_mode = "otg"; -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 19/19] arm: dts: am43x evms: Make usb1 as OTG
USB1 of am43x EPOS EVM, am437x GP EVM and am437x SK EVM can be used as OTG. Enable the same. Signed-off-by: George Cherian --- arch/arm/boot/dts/am437x-gp-evm.dts | 2 +- arch/arm/boot/dts/am437x-sk-evm.dts | 2 +- arch/arm/boot/dts/am43x-epos-evm.dts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts b/arch/arm/boot/dts/am437x-gp-evm.dts index e7ac47f..a8b5752 100644 --- a/arch/arm/boot/dts/am437x-gp-evm.dts +++ b/arch/arm/boot/dts/am437x-gp-evm.dts @@ -380,7 +380,7 @@ }; &usb1 { - dr_mode = "peripheral"; + dr_mode = "otg"; status = "okay"; }; diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts index 859ff3d..b258826 100644 --- a/arch/arm/boot/dts/am437x-sk-evm.dts +++ b/arch/arm/boot/dts/am437x-sk-evm.dts @@ -478,7 +478,7 @@ }; &usb1 { - dr_mode = "peripheral"; + dr_mode = "otg"; status = "okay"; }; diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts index ac3e485..3d106e9 100644 --- a/arch/arm/boot/dts/am43x-epos-evm.dts +++ b/arch/arm/boot/dts/am43x-epos-evm.dts @@ -542,7 +542,7 @@ }; &usb1 { - dr_mode = "peripheral"; + dr_mode = "otg"; status = "okay"; }; -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 00/19] Add Support for USB DRD in AM437x
The series add DRD suport for AM437x. The serires adds - USB DRD Library This Library facilitates in switching roles between HOST and Device. - DWC3 OTG driver. This driver currently suports only the ID based switching Felipe Balbi (2): usb: dwc3: core: Adapt to named interrupts arm: dts: am4372: Add named interrupt property for dwc3 George Cherian (17): usb: common: drd-lib: Add DRD lib for USB. usb: host xhci: fix up deallocation code usb: host: xhci-plat: Add support to pass XHCI_DRD_SUPPORT quirk usb: host xhci: Add XHCI_NEEDS_LHC_RESET quirk usb: host: xhci-plat: Add support to pass XHCI_NEEDS_LHC_RESET quirk usb: dwc3: host: Pass the XHCI_DRD_SUPPORT and XHCI_NEEDS_LHC_RESET quirk usb: host: xhci: Adapt xhci to use usb drd library usb: dwc3: core: Add dwc3_drd_helper function usb: dwc3: dwc3-omap: Make the wrapper interrupt shared usb: dwc3: Add seperate dwc3_gadget object to support gadget release usb: dwc3: gadget: Adapt gadget to drd library usb: dwc3: core: Add DWC3 OTG specific register defines usb: dwc3: otg: Add the initial otg driver for dwc3. arm: dts: omap5: Add named interrupt property for dwc3 arm: dts: dra7: Add named interrupt property for dwc3 arm: dts: exynos5250: Add named interrupt property for dwc3 arm: dts: am43x evms: Make usb1 as OTG arch/arm/boot/dts/am4372.dtsi| 18 +- arch/arm/boot/dts/am437x-gp-evm.dts | 2 +- arch/arm/boot/dts/am437x-sk-evm.dts | 2 +- arch/arm/boot/dts/am43x-epos-evm.dts | 2 +- arch/arm/boot/dts/dra7.dtsi | 28 ++- arch/arm/boot/dts/exynos5250.dtsi| 7 +- arch/arm/boot/dts/omap5.dtsi | 7 +- drivers/usb/Kconfig | 15 ++ drivers/usb/common/Makefile | 1 + drivers/usb/common/drd-lib.c | 346 +++ drivers/usb/dwc3/Makefile| 4 + drivers/usb/dwc3/core.c | 27 ++- drivers/usb/dwc3/core.h | 93 +- drivers/usb/dwc3/dwc3-omap.c | 4 +- drivers/usb/dwc3/ep0.c | 35 ++-- drivers/usb/dwc3/gadget.c| 211 +++-- drivers/usb/dwc3/gadget.h| 1 + drivers/usb/dwc3/host.c | 2 + drivers/usb/dwc3/otg.c | 126 + drivers/usb/host/xhci-plat.c | 22 +++ drivers/usb/host/xhci.c | 27 ++- drivers/usb/host/xhci.h | 2 + include/linux/usb/drd.h | 77 include/linux/usb/xhci_pdriver.h | 2 + 24 files changed, 962 insertions(+), 99 deletions(-) create mode 100644 drivers/usb/common/drd-lib.c create mode 100644 drivers/usb/dwc3/otg.c create mode 100644 include/linux/usb/drd.h -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RESEND PATCH 1/2] extcon: gpio: Add dt support for the driver
Add device tree support to extcon-gpio driver. Add devicetree binding documentation While at that - Cleanup the pdata as there are no users for the same. - Convert the driver to use gpiod_* API's. - Some gpio's can sleep while reading, so always use gpio_get_value_cansleep to get data. This fixes warning from gpiolib due to wrong API usage. Signed-off-by: George Cherian --- .../devicetree/bindings/extcon/extcon-gpio.txt | 21 ++ drivers/extcon/extcon-gpio.c | 83 +++--- include/linux/extcon/extcon-gpio.h | 59 --- 3 files changed, 46 insertions(+), 117 deletions(-) create mode 100644 Documentation/devicetree/bindings/extcon/extcon-gpio.txt delete mode 100644 include/linux/extcon/extcon-gpio.h diff --git a/Documentation/devicetree/bindings/extcon/extcon-gpio.txt b/Documentation/devicetree/bindings/extcon/extcon-gpio.txt new file mode 100644 index 000..30aa2e1 --- /dev/null +++ b/Documentation/devicetree/bindings/extcon/extcon-gpio.txt @@ -0,0 +1,21 @@ +GPIO based EXTCON + +EXTCON GPIO +--- + +Required Properties: + - compatible: should be: + * "linux,extcon-gpio" + - gpios: specifies the gpio pin used. + +Optional Properties: + - debounce: Debounce time for GPIO IRQ in ms + + +Eg: + + extcon1: am43_usbid_extcon1 { + compatible = "linux,extcon-gpio"; + gpios = <&gpio3 12 GPIO_ACTIVE_HIGH>; + debounce = <20>; + }; diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c index 72f19a3..85795de 100644 --- a/drivers/extcon/extcon-gpio.c +++ b/drivers/extcon/extcon-gpio.c @@ -21,26 +21,23 @@ */ #include -#include #include #include #include +#include #include #include +#include #include #include #include struct gpio_extcon_data { struct extcon_dev *edev; - unsigned gpio; - bool gpio_active_low; - const char *state_on; - const char *state_off; + struct gpio_desc *gpiod; int irq; struct delayed_work work; unsigned long debounce_jiffies; - bool check_on_resume; }; static void gpio_extcon_work(struct work_struct *work) @@ -50,9 +47,7 @@ static void gpio_extcon_work(struct work_struct *work) container_of(to_delayed_work(work), struct gpio_extcon_data, work); - state = gpio_get_value(data->gpio); - if (data->gpio_active_low) - state = !state; + state = gpiod_get_value_cansleep(data->gpiod); extcon_set_state(data->edev, state); } @@ -65,34 +60,16 @@ static irqreturn_t gpio_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } -static ssize_t extcon_gpio_print_state(struct extcon_dev *edev, char *buf) -{ - struct device *dev = edev->dev.parent; - struct gpio_extcon_data *extcon_data = dev_get_drvdata(dev); - const char *state; - - if (extcon_get_state(edev)) - state = extcon_data->state_on; - else - state = extcon_data->state_off; - - if (state) - return sprintf(buf, "%s\n", state); - return -EINVAL; -} - static int gpio_extcon_probe(struct platform_device *pdev) { - struct gpio_extcon_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct device_node *np = pdev->dev.of_node; struct gpio_extcon_data *extcon_data; + unsigned int irq_flags; + unsigned int debounce = 0; int ret; - if (!pdata) - return -EBUSY; - if (!pdata->irq_flags) { - dev_err(&pdev->dev, "IRQ flag is not specified.\n"); + if (!np) return -EINVAL; - } extcon_data = devm_kzalloc(&pdev->dev, sizeof(struct gpio_extcon_data), GFP_KERNEL); @@ -104,27 +81,23 @@ static int gpio_extcon_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to allocate extcon device\n"); return -ENOMEM; } - extcon_data->edev->name = pdata->name; - - extcon_data->gpio = pdata->gpio; - extcon_data->gpio_active_low = pdata->gpio_active_low; - extcon_data->state_on = pdata->state_on; - extcon_data->state_off = pdata->state_off; - extcon_data->check_on_resume = pdata->check_on_resume; - if (pdata->state_on && pdata->state_off) - extcon_data->edev->print_state = extcon_gpio_print_state; - - ret = devm_gpio_request_one(&pdev->dev, extcon_data->gpio, GPIOF_DIR_IN, - pdev->name); - if (ret < 0) - return ret; + extcon_data->edev->name = np->name; +
[RESEND PATCH 0/2] Add dt support for extcon gpio driver
This series - Adds dt support to extcon-gpio driver. - Add cable name support in case of dt. George Cherian (2): extcon: gpio: Add dt support for the driver extcon: gpio: Add support for using cable names drivers/extcon/extcon-gpio.c | 87 +- include/linux/extcon/extcon-gpio.h | 59 -- 2 files changed, 29 insertions(+), 117 deletions(-) delete mode 100644 include/linux/extcon/extcon-gpio.h -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RESEND PATCH 2/2] extcon: gpio: Add support for using cable names
Add support for using cable names. Enables other drivers to register interest and get notified using extcon provided notifier call backs. Signed-off-by: George Cherian --- Documentation/devicetree/bindings/extcon/extcon-gpio.txt | 2 ++ drivers/extcon/extcon-gpio.c | 4 2 files changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/extcon/extcon-gpio.txt b/Documentation/devicetree/bindings/extcon/extcon-gpio.txt index 30aa2e1..2c9d29f 100644 --- a/Documentation/devicetree/bindings/extcon/extcon-gpio.txt +++ b/Documentation/devicetree/bindings/extcon/extcon-gpio.txt @@ -7,6 +7,7 @@ Required Properties: - compatible: should be: * "linux,extcon-gpio" - gpios: specifies the gpio pin used. + - cable-name: Name of the cable used. Optional Properties: - debounce: Debounce time for GPIO IRQ in ms @@ -18,4 +19,5 @@ Eg: compatible = "linux,extcon-gpio"; gpios = <&gpio3 12 GPIO_ACTIVE_HIGH>; debounce = <20>; + cable-name = "USB-HOST"; }; diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c index 85795de..0e1b3e8 100644 --- a/drivers/extcon/extcon-gpio.c +++ b/drivers/extcon/extcon-gpio.c @@ -38,6 +38,7 @@ struct gpio_extcon_data { int irq; struct delayed_work work; unsigned long debounce_jiffies; + const char *cable_name[1]; }; static void gpio_extcon_work(struct work_struct *work) @@ -100,6 +101,9 @@ static int gpio_extcon_probe(struct platform_device *pdev) msecs_to_jiffies(debounce); } + of_property_read_string_index(np, "cable-name", 0, + extcon_data->cable_name); + extcon_data->edev->supported_cable = extcon_data->cable_name; ret = devm_extcon_dev_register(&pdev->dev, extcon_data->edev); if (ret < 0) return ret; -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 0/4] extcon: gpio: add DT support
On 11/04/2014 08:11 PM, Felipe Balbi wrote: On Tue, Nov 04, 2014 at 11:42:04AM +0530, George Cherian wrote: Hi Felipe et al. Another series was posted by removing the platform support. https://lkml.org/lkml/2014/10/14/244 I guess I forgot to copy linux-omap. you do too many things in patch one. I wonder why you decided to combine three patches in one for that series. Since there are no platform users for this driver. I am basically removing the whole platform data part from the driver. That is the reason i squashed 1 to 3 of the previous series. I will resend the new series copying linux-omap now. -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 0/4] extcon: gpio: add DT support
Hi Felipe et al. Another series was posted by removing the platform support. https://lkml.org/lkml/2014/10/14/244 I guess I forgot to copy linux-omap. On 11/03/2014 10:02 PM, Felipe Balbi wrote: Hi, this series has been tested with v3.18-rc2 with a yet-to-be-released board (called X15). That board is DT-only and we use extcon-gpio to decide which USB mode should be used (host or peripheral). George Cherian (4): extcon: gpio: Convert the driver to use gpio desc API's extcon: gpio: Add dt support for the driver. extcon: gpio: Always use gpio_get_value_cansleep extcon: gpio: Add support for using cable names .../devicetree/bindings/extcon/extcon-gpio.txt | 23 ++ drivers/extcon/extcon-gpio.c | 93 ++ 2 files changed, 84 insertions(+), 32 deletions(-) create mode 100644 Documentation/devicetree/bindings/extcon/extcon-gpio.txt -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Gadget regression with enabling of MUSB babble interrupt handling
On 6/19/2014 4:54 PM, Tony Lindgren wrote: * Daniel Mack [140619 03:51]: On 06/19/2014 12:43 PM, Tony Lindgren wrote: * Daniel Mack [140619 03:38]: On 06/19/2014 12:31 PM, Tony Lindgren wrote: * Daniel Mack [140619 03:10]: On 06/19/2014 11:56 AM, Tony Lindgren wrote: But that also raises a question: Were these patches merged for v3.16 ever even tested in peripheral mode? At the time, I had no such hardware to test this on, so I was hoping for more testers to give them a try in different environments, which apparently didn't happen. It fixed a dead USB port condition on host-mode enabled hardware, though. Well we probably should not merge patches without proper acks and tested-by:s in general as things just seem to keep breaking constantly otherwise. And things not working will keep people from using linux next which will lead into even less testing.. I'm fairly sure the patch causing your trouble has been in linux-next for a while before they hit the merge window, so people with gadget enabled musb could have noticed the breakage early enough. The feedback rate for patches to this driver posted to linux-usb is also usually low, unfortunately. I blame myself for not explicitly pointing out the fix. Instead I clubbed it with this series. http://marc.info/?l=linux-usb&m=140109627505065&w=4 Sorry for that. Right but the problem is that people are not touching linux next because it's constantly broken :) Anyway, breaking things is certainly not good, and I'm sorry for that. I'm just uncertain what detail in the procedure should be tweaked in order to prevent that from happening in the future. Well I guess somebody should run basic tests on this driver in linux next, that would probably solve the issues. I am doing it. Regards, Tony -- -George -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] ARM: dts: am43x-epos-evm: Add Missing cpsw-phy-sel for am43x-epos-evm
On 6/6/2014 12:25 PM, Nishanth Menon wrote: On 06/06/2014 01:53 AM, Nishanth Menon wrote: On 06/06/2014 01:17 AM, George Cherian wrote: AM437x EPOS evm use external clock for RMII interface. Enable the same in DT. Signed-off-by: George Cherian Reported-by: Nishanth Menon --- arch/arm/boot/dts/am43x-epos-evm.dts | 4 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts index 19f1f7e..90098f9 100644 --- a/arch/arm/boot/dts/am43x-epos-evm.dts +++ b/arch/arm/boot/dts/am43x-epos-evm.dts @@ -319,6 +319,10 @@ phy-mode = "rmii"; }; +&phy_sel { + rmii-clock-ext; +}; + &i2c0 { status = "okay"; pinctrl-names = "default"; Where does this apply on? With linux-next next-20140506 tag, and this patch applied, I get the following error. LD kernel/trace/built-in.o LD kernel/built-in.o build fail, Error: Error: arch/arm/boot/dts/am43x-epos-evm.dts:219.2-3 label or path, 'phy_sel', not found FATAL ERROR: Syntax error parsing input tree make[1]: *** [arch/arm/boot/dts/am43x-epos-evm.dtb] Error 1 make[1]: *** Waiting for unfinished jobs make: *** [dtbs] Error 2 make: *** Waiting for unfinished jobs in the future, it is helpful if you can point out that this is a regression seen on next-20140603 and the patch needs to be applied on some specific branch. for the record: last working next tag: https://github.com/nmenon/kernel-test-logs/blob/next-20140602/omap2plus_defconfig/am43xx-epos.txt first broken next tag: https://github.com/nmenon/kernel-test-logs/blob/next-20140603/omap2plus_defconfig/am43xx-epos.txt interestingly, i just re-tested today's tag without the patch (omap2plus_defconfig): http://slexy.org/raw/s205sRdFvy Lil old kernel from the above link. Linux version 3.15.0-rc4-next-20140506 (nmenon@kahuna) (gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) ) #2 SMP Fri Jun 6 01:47:42 CDT 2014 I wonder why the behavior change and what was being fixed here? This kernel should not have the dt entries for phy sel driver. Thats why it is working. -- -George -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] ARM: dts: am43x-epos-evm: Add Missing cpsw-phy-sel for am43x-epos-evm
On 6/6/2014 12:23 PM, Nishanth Menon wrote: On 06/06/2014 01:17 AM, George Cherian wrote: AM437x EPOS evm use external clock for RMII interface. Enable the same in DT. Signed-off-by: George Cherian Reported-by: Nishanth Menon --- arch/arm/boot/dts/am43x-epos-evm.dts | 4 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts index 19f1f7e..90098f9 100644 --- a/arch/arm/boot/dts/am43x-epos-evm.dts +++ b/arch/arm/boot/dts/am43x-epos-evm.dts @@ -319,6 +319,10 @@ phy-mode = "rmii"; }; +&phy_sel { + rmii-clock-ext; +}; + &i2c0 { status = "okay"; pinctrl-names = "default"; Where does this apply on? With linux-next next-20140506 tag, and this patch applied, I get the Is'nt next-20140506 a month old. I tried the patch on next-20140604. following error. LD kernel/trace/built-in.o LD kernel/built-in.o build fail, Error: Error: arch/arm/boot/dts/am43x-epos-evm.dts:219.2-3 label or path, 'phy_sel', not found FATAL ERROR: Syntax error parsing input tree make[1]: *** [arch/arm/boot/dts/am43x-epos-evm.dtb] Error 1 make[1]: *** Waiting for unfinished jobs make: *** [dtbs] Error 2 make: *** Waiting for unfinished jobs in the future, it is helpful if you can point out that this is a regression seen on next-20140603 and the patch needs to be applied on some specific branch. for the record: last working next tag: https://github.com/nmenon/kernel-test-logs/blob/next-20140602/omap2plus_defconfig/am43xx-epos.txt first broken next tag: https://github.com/nmenon/kernel-test-logs/blob/next-20140603/omap2plus_defconfig/am43xx-epos.txt -- -George -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] ARM: dts: am43x-epos-evm: Add Missing cpsw-phy-sel for am43x-epos-evm
AM437x EPOS evm use external clock for RMII interface. Enable the same in DT. Signed-off-by: George Cherian Reported-by: Nishanth Menon --- arch/arm/boot/dts/am43x-epos-evm.dts | 4 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts index 19f1f7e..90098f9 100644 --- a/arch/arm/boot/dts/am43x-epos-evm.dts +++ b/arch/arm/boot/dts/am43x-epos-evm.dts @@ -319,6 +319,10 @@ phy-mode = "rmii"; }; +&phy_sel { + rmii-clock-ext; +}; + &i2c0 { status = "okay"; pinctrl-names = "default"; -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v6 1/5] usb: musb: core: Handle Babble condition only in HOST mode
BABBLE and RESET share the same interrupt. The interrupt is considered to be RESET if MUSB is in peripheral mode and as a BABBLE if MUSB is in HOST mode. Handle babble condition iff MUSB is in HOST mode. Signed-off-by: George Cherian --- drivers/usb/musb/musb_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 3c6043c..0ad9551 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -849,7 +849,7 @@ b_host: } /* handle babble condition */ - if (int_usb & MUSB_INTR_BABBLE) + if (int_usb & MUSB_INTR_BABBLE && is_host_active(musb)) schedule_work(&musb->recover_work); #if 0 -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v6 2/5] usb: musb: core: Convert babble recover work to delayed work
During babble condition both first disconnect of devices are initiated. Make sure MUSB controller is reset and re-initialized after all disconnects. To acheive this schedule a delayed work for babble recovery. While at that convert udelay to usleep_range. Refer Documentation/timers/timers-howto.txt Signed-off-by: George Cherian --- drivers/usb/musb/musb_core.c | 15 --- drivers/usb/musb/musb_core.h | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 0ad9551..c0ce09f 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -850,7 +850,8 @@ b_host: /* handle babble condition */ if (int_usb & MUSB_INTR_BABBLE && is_host_active(musb)) - schedule_work(&musb->recover_work); + schedule_delayed_work(&musb->recover_work, + msecs_to_jiffies(100)); #if 0 /* REVISIT ... this would be for multiplexing periodic endpoints, or @@ -1751,16 +1752,16 @@ static void musb_irq_work(struct work_struct *data) /* Recover from babble interrupt conditions */ static void musb_recover_work(struct work_struct *data) { - struct musb *musb = container_of(data, struct musb, recover_work); + struct musb *musb = container_of(data, struct musb, recover_work.work); int status; musb_platform_reset(musb); usb_phy_vbus_off(musb->xceiv); - udelay(100); + usleep_range(100, 200); usb_phy_vbus_on(musb->xceiv); - udelay(100); + usleep_range(100, 200); /* * When a babble condition occurs, the musb controller removes the @@ -1943,7 +1944,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) /* Init IRQ workqueue before request_irq */ INIT_WORK(&musb->irq_work, musb_irq_work); - INIT_WORK(&musb->recover_work, musb_recover_work); + INIT_DELAYED_WORK(&musb->recover_work, musb_recover_work); INIT_DELAYED_WORK(&musb->deassert_reset_work, musb_deassert_reset); INIT_DELAYED_WORK(&musb->finish_resume_work, musb_host_finish_resume); @@ -2039,7 +2040,7 @@ fail4: fail3: cancel_work_sync(&musb->irq_work); - cancel_work_sync(&musb->recover_work); + cancel_delayed_work_sync(&musb->recover_work); cancel_delayed_work_sync(&musb->finish_resume_work); cancel_delayed_work_sync(&musb->deassert_reset_work); if (musb->dma_controller) @@ -2105,7 +2106,7 @@ static int musb_remove(struct platform_device *pdev) dma_controller_destroy(musb->dma_controller); cancel_work_sync(&musb->irq_work); - cancel_work_sync(&musb->recover_work); + cancel_delayed_work_sync(&musb->recover_work); cancel_delayed_work_sync(&musb->finish_resume_work); cancel_delayed_work_sync(&musb->deassert_reset_work); musb_free(musb); diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index d155a15..9241025 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -297,7 +297,7 @@ struct musb { irqreturn_t (*isr)(int, void *); struct work_struct irq_work; - struct work_struct recover_work; + struct delayed_work recover_work; struct delayed_work deassert_reset_work; struct delayed_work finish_resume_work; u16 hwvers; -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v6 0/5] Add support for SW babble Control
Series add support for SW babble control logic found in new silicon versions of AM335x. Runtime differentiation of silicon version is done by checking the BABBLE_CTL register. For newer silicon the register default value read is 0x4 and for older versions its 0x0. Patch 1 -> Handle Babble only if MUSB is in HOST mode Patch 2 -> Convert recover work to delayed work. Patch 3 -> usb_phy_vbus_(off/_on) are NOPs for am335x PHY so use usb_phy(_shutdown/_init) in musb_platform_reset() Patch 4 -> Add return value for musb_platform_reset() in prepration to support SW babble_ctrl Patch 5 -> Add and Enable sw babble control for newer silicon v5 -> v6 : Squash patch 5 and 6 form v5 to avoid build warnings. v4 -> v5 : Added a debug print before resetting MUSB. changed a musb_readb to dsps_readb introduced in Patch#5 of v4. v3 -> v4 : Fixes an issue in gagdet mode - BUS RESET should not be handled as a BABBLE. Added a check for the same.(Patch #1) Enable sw babble control properly (Patch #6) v2 -> v3 : Modify musb_platform_reset() to return zero on success. George Cherian (5): usb: musb: core: Handle Babble condition only in HOST mode usb: musb: core: Convert babble recover work to delayed work usb: musb: dsps: Call usb_phy(_shutdown/_init) during musb_platform_reset() usb: musb: core: Convert the musb_platform_reset to have a return value. usb: musb: dsps: Add the sw_babble_control() and Enable for newer silicon drivers/usb/musb/musb_core.c | 27 -- drivers/usb/musb/musb_core.h | 12 +++--- drivers/usb/musb/musb_dsps.c | 88 ++-- drivers/usb/musb/musb_regs.h | 7 4 files changed, 114 insertions(+), 20 deletions(-) -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v6 3/5] usb: musb: dsps: Call usb_phy(_shutdown/_init) during musb_platform_reset()
For DSPS platform usb_phy_vbus(_off/_on) are NOPs. So during musb_platform_reset() call usb_phy(_shutdown/_init) Signed-off-by: George Cherian --- drivers/usb/musb/musb_dsps.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 51beb13..74c4193 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -543,7 +543,11 @@ static void dsps_musb_reset(struct musb *musb) const struct dsps_musb_wrapper *wrp = glue->wrp; dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset)); - udelay(100); + usleep_range(100, 200); + usb_phy_shutdown(musb->xceiv); + usleep_range(100, 200); + usb_phy_init(musb->xceiv); + } static struct musb_platform_ops dsps_ops = { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v6 5/5] usb: musb: dsps: Add the sw_babble_control() and Enable for newer silicon
Add sw_babble_control() logic to differentiate between transient babble and real babble condition. Also add the SW babble control register definitions. Babble control register logic is implemented in the latest revision of AM335x. Find whether we are running on newer silicon. The babble control register reads 0x4 by default in newer silicon as opposed to 0 in old versions of AM335x. Based on this enable the sw babble control logic. Signed-off-by: George Cherian --- drivers/usb/musb/musb_dsps.c | 89 +--- drivers/usb/musb/musb_regs.h | 7 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index f6f3087..01543a9 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -136,6 +136,7 @@ struct dsps_glue { const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */ struct timer_list timer;/* otg_workaround timer */ unsigned long last_timer;/* last timer data for each instance */ + bool sw_babble_enabled; struct dsps_context context; struct debugfs_regset32 regset; @@ -469,6 +470,19 @@ static int dsps_musb_init(struct musb *musb) val &= ~(1 << wrp->otg_disable); dsps_writel(musb->ctrl_base, wrp->phy_utmi, val); + /* +* Check whether the dsps version has babble control enabled. +* In latest silicon revision the babble control logic is enabled. +* If MUSB_BABBLE_CTL returns 0x4 then we have the babble control +* logic enabled. +*/ + val = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); + if (val == MUSB_BABBLE_RCV_DISABLE) { + glue->sw_babble_enabled = true; + val |= MUSB_BABBLE_SW_SESSION_CTRL; + dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, val); + } + ret = dsps_musb_dbg_init(musb, glue); if (ret) return ret; @@ -536,19 +550,82 @@ static int dsps_musb_set_mode(struct musb *musb, u8 mode) return 0; } +static bool sw_babble_control(struct musb *musb) +{ + u8 babble_ctl; + bool session_restart = false; + + babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); + dev_dbg(musb->controller, "babble: MUSB_BABBLE_CTL value %x\n", + babble_ctl); + /* +* check line monitor flag to check whether babble is +* due to noise +*/ + dev_dbg(musb->controller, "STUCK_J is %s\n", + babble_ctl & MUSB_BABBLE_STUCK_J ? "set" : "reset"); + + if (babble_ctl & MUSB_BABBLE_STUCK_J) { + int timeout = 10; + + /* +* babble is due to noise, then set transmit idle (d7 bit) +* to resume normal operation +*/ + babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); + babble_ctl |= MUSB_BABBLE_FORCE_TXIDLE; + dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, babble_ctl); + + /* wait till line monitor flag cleared */ + dev_dbg(musb->controller, "Set TXIDLE, wait J to clear\n"); + do { + babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); + udelay(1); + } while ((babble_ctl & MUSB_BABBLE_STUCK_J) && timeout--); + + /* check whether stuck_at_j bit cleared */ + if (babble_ctl & MUSB_BABBLE_STUCK_J) { + /* +* real babble condition has occurred +* restart the controller to start the +* session again +*/ + dev_dbg(musb->controller, "J not cleared, misc (%x)\n", + babble_ctl); + session_restart = true; + } + } else { + session_restart = true; + } + + return session_restart; +} + static int dsps_musb_reset(struct musb *musb) { struct device *dev = musb->controller; struct dsps_glue *glue = dev_get_drvdata(dev->parent); const struct dsps_musb_wrapper *wrp = glue->wrp; + int session_restart = 0; - dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset)); - usleep_range(100, 200); - usb_phy_shutdown(musb->xceiv); - usleep_range(100, 200); - usb_phy_init(musb->xceiv); + if (glue->sw_babble_enabled) + session_restart = sw_babble_control(musb); + /* +* In case of new silicon version babble condition can be recovered +* without resetting the MUSB. But for older silicon versions, MUSB +* reset is needed +*/ + if (session_restart
[PATCH v6 4/5] usb: musb: core: Convert the musb_platform_reset to have a return value.
Currently musb_platform_reset() is only used by dsps. In case of BABBLE interrupt for other platforms the musb_platform_reset() is a NOP. In such situations no need to re-initialize the endpoints. Also in the latest silicon revision of AM335x, we do have a babble recovery mechanism without resetting the IP block. In preperation to add that support its better to have a rest_done return for musb_platform_reset(). Signed-off-by: George Cherian --- drivers/usb/musb/musb_core.c | 10 ++ drivers/usb/musb/musb_core.h | 10 ++ drivers/usb/musb/musb_dsps.c | 3 ++- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index c0ce09f..b841ee0 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1753,9 +1753,11 @@ static void musb_irq_work(struct work_struct *data) static void musb_recover_work(struct work_struct *data) { struct musb *musb = container_of(data, struct musb, recover_work.work); - int status; + int status, ret; - musb_platform_reset(musb); + ret = musb_platform_reset(musb); + if (ret) + return; usb_phy_vbus_off(musb->xceiv); usleep_range(100, 200); @@ -1764,8 +1766,8 @@ static void musb_recover_work(struct work_struct *data) usleep_range(100, 200); /* -* When a babble condition occurs, the musb controller removes the -* session bit and the endpoint config is lost. +* When a babble condition occurs, the musb controller +* removes the session bit and the endpoint config is lost. */ if (musb->dyn_fifo) status = ep_config_from_table(musb); diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 9241025..414e57a 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -192,7 +192,7 @@ struct musb_platform_ops { int (*set_mode)(struct musb *musb, u8 mode); void(*try_idle)(struct musb *musb, unsigned long timeout); - void(*reset)(struct musb *musb); + int (*reset)(struct musb *musb); int (*vbus_status)(struct musb *musb); void(*set_vbus)(struct musb *musb, int on); @@ -555,10 +555,12 @@ static inline void musb_platform_try_idle(struct musb *musb, musb->ops->try_idle(musb, timeout); } -static inline void musb_platform_reset(struct musb *musb) +static inline int musb_platform_reset(struct musb *musb) { - if (musb->ops->reset) - musb->ops->reset(musb); + if (!musb->ops->reset) + return -EINVAL; + + return musb->ops->reset(musb); } static inline int musb_platform_get_vbus_status(struct musb *musb) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 74c4193..f6f3087 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -536,7 +536,7 @@ static int dsps_musb_set_mode(struct musb *musb, u8 mode) return 0; } -static void dsps_musb_reset(struct musb *musb) +static int dsps_musb_reset(struct musb *musb) { struct device *dev = musb->controller; struct dsps_glue *glue = dev_get_drvdata(dev->parent); @@ -548,6 +548,7 @@ static void dsps_musb_reset(struct musb *musb) usleep_range(100, 200); usb_phy_init(musb->xceiv); + return 0; } static struct musb_platform_ops dsps_ops = { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 1/6] usb: musb: core: Handle Babble condition only in HOST mode
On 5/23/2014 2:12 AM, Bin Liu wrote: Hi George, On Mon, May 19, 2014 at 11:32 PM, George Cherian wrote: Hi Bin, On 5/19/2014 9:24 PM, Bin Liu wrote: Hi, On Mon, May 19, 2014 at 8:39 AM, George Cherian wrote: BABBLE and RESET share the same interrupt. The interrupt is considered to be RESET if MUSB is in peripheral mode and as a BABBLE if MUSB is in HOST mode. Handle babble condition iff MUSB is in HOST mode. Signed-off-by: George Cherian --- drivers/usb/musb/musb_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 61da471..eff3c5c 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -849,7 +849,7 @@ b_host: } /* handle babble condition */ - if (int_usb & MUSB_INTR_BABBLE) + if (int_usb & MUSB_INTR_BABBLE && is_host_active(musb)) schedule_work(&musb->recover_work); I guess my following comments are for Daniel's patch as while which initially added the babble work. Should this if statement be merged into the previous 'if(int_usb & MUSB_INTR_RESET)' one, which handles the same interrupt and already handles host and device mode respectively. Initially I too had the babble handling as part of 'if(int_usb & MUSB_INTR_RESET)' one. But during my tests I hit a corner case where in we hit a BABBLE condition on disconnect. In such case the babble interrupt can be handled only if we have a seperate check, else its considered as a BUS RESET. When all devices are disconnected MUSB_DEVCTL_HM = 0 and the code always enter the else path. In this path it treats the BABBLE as a BUS RESET. The code flow is a bit confusing, two if() handle the same interrupt. The second one implied using 'handled = IRQ_HANDLED;' from the first one. Also does the switch() in else{} in the first if() cause any side effect? No it doesn't. Since this babble handing is AM335x specific, how about handle it in dsps_interrupt() in musb_dsps.c, which already has an entry for babble interrupt? TI 3.2 kernel does this way. That the reason we have platform specific callbacks added from the main interrupt handler. Regards, -Bin. Regards, -Bin. #if 0 -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- -George -- -George -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v5 6/6] usb: musb: dsps: Enable sw babble control for newer silicon
On 5/22/2014 5:28 PM, Sergei Shtylyov wrote: Hello. On 22-05-2014 10:29, George Cherian wrote: Find whether we are running on newer silicon. The babble control register reads 0x4 by default in newer silicon as opposed to 0 in old versions of AM335x. Based on this enable the sw babble control logic. Signed-off-by: George Cherian --- drivers/usb/musb/musb_dsps.c | 38 -- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 868caf8..2ced061 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c [...] @@ -469,6 +470,19 @@ static int dsps_musb_init(struct musb *musb) val &= ~(1 << wrp->otg_disable); dsps_writel(musb->ctrl_base, wrp->phy_utmi, val); +/* + * Check whether the dsps version has babble control enabled. One space too many before this sentence. + * In latest silicon revision the babble control logic is enabled. + * If MUSB_BABBLE_CTL returns 0x4 then we have the babble control + * logic enabled. + */ +val = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); +if (val == MUSB_BABBLE_RCV_DISABLE) { +glue->sw_babble_enabled = true; +val |= MUSB_BABBLE_SW_SESSION_CTRL; +dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, val); +} + Hm, from the register offset that you declared in the previous patch, I got an impression that this is a new standard MUSB register? Its very AM335x MUSB specific register, not a standard one. Unfortunately the designers put it as part of MUSB core regs. Shouldn't this check be done in the generic MUSB code then? WBR, Sergei -- -George -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 0/6] Add support for SW babble Control
Series add support for SW babble control logic found in new silicon versions of AM335x. Runtime differentiation of silicon version is done by checking the BABBLE_CTL register. For newer silicon the register default value read is 0x4 and for older versions its 0x0. Patch 1 -> Handle Babble only if MUSB is in HOST mode Patch 2 -> Convert recover work to delayed work. Patch 3 -> usb_phy_vbus_(off/_on) are NOPs for am335x PHY so use usb_phy(_shutdown/_init) in musb_platform_reset() Patch 4 -> Add return value for musb_platform_reset() in prepration to support SW babble_ctrl Patch 5 -> Add the sw_babble_control() Patch 6 -> Enable sw babble control for newer silicon v4 -> v5 : Added a debug print before resetting MUSB. changed a musb_readb to dsps_readb introduced in Patch#5 of v4. v3 -> v4 : Fixes an issue in gagdet mode - BUS RESET should not be handled as a BABBLE. Added a check for the same.(Patch #1) Enable sw babble control properly (Patch #6) v2 -> v3 : Modify musb_platform_reset() to return zero on success. George Cherian (6): usb: musb: core: Handle Babble condition only in HOST mode usb: musb: core: Convert babble recover work to delayed work usb: musb: dsps: Call usb_phy(_shutdown/_init) during musb_platform_reset() usb: musb: core: Convert the musb_platform_reset to have a return value. usb: musb: dsps: Add the sw_babble_control() usb: musb: dsps: Enable sw babble control for newer silicon drivers/usb/musb/musb_core.c | 27 -- drivers/usb/musb/musb_core.h | 12 +++--- drivers/usb/musb/musb_dsps.c | 87 ++-- drivers/usb/musb/musb_regs.h | 7 4 files changed, 113 insertions(+), 20 deletions(-) -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 2/6] usb: musb: core: Convert babble recover work to delayed work
During babble condition both first disconnect of devices are initiated. Make sure MUSB controller is reset and re-initialized after all disconnects. To acheive this schedule a delayed work for babble rrecovery. While at that convert udelay to usleep_range. Refer Documentation/timers/timers-howto.txt Signed-off-by: George Cherian --- drivers/usb/musb/musb_core.c | 15 --- drivers/usb/musb/musb_core.h | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index eff3c5c..8920b80 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -850,7 +850,8 @@ b_host: /* handle babble condition */ if (int_usb & MUSB_INTR_BABBLE && is_host_active(musb)) - schedule_work(&musb->recover_work); + schedule_delayed_work(&musb->recover_work, + msecs_to_jiffies(100)); #if 0 /* REVISIT ... this would be for multiplexing periodic endpoints, or @@ -1753,16 +1754,16 @@ static void musb_irq_work(struct work_struct *data) /* Recover from babble interrupt conditions */ static void musb_recover_work(struct work_struct *data) { - struct musb *musb = container_of(data, struct musb, recover_work); + struct musb *musb = container_of(data, struct musb, recover_work.work); int status; musb_platform_reset(musb); usb_phy_vbus_off(musb->xceiv); - udelay(100); + usleep_range(100, 200); usb_phy_vbus_on(musb->xceiv); - udelay(100); + usleep_range(100, 200); /* * When a babble condition occurs, the musb controller removes the @@ -1945,7 +1946,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) /* Init IRQ workqueue before request_irq */ INIT_WORK(&musb->irq_work, musb_irq_work); - INIT_WORK(&musb->recover_work, musb_recover_work); + INIT_DELAYED_WORK(&musb->recover_work, musb_recover_work); INIT_DELAYED_WORK(&musb->deassert_reset_work, musb_deassert_reset); INIT_DELAYED_WORK(&musb->finish_resume_work, musb_host_finish_resume); @@ -2041,7 +2042,7 @@ fail4: fail3: cancel_work_sync(&musb->irq_work); - cancel_work_sync(&musb->recover_work); + cancel_delayed_work_sync(&musb->recover_work); cancel_delayed_work_sync(&musb->finish_resume_work); cancel_delayed_work_sync(&musb->deassert_reset_work); if (musb->dma_controller) @@ -2107,7 +2108,7 @@ static int musb_remove(struct platform_device *pdev) dma_controller_destroy(musb->dma_controller); cancel_work_sync(&musb->irq_work); - cancel_work_sync(&musb->recover_work); + cancel_delayed_work_sync(&musb->recover_work); cancel_delayed_work_sync(&musb->finish_resume_work); cancel_delayed_work_sync(&musb->deassert_reset_work); musb_free(musb); diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index d155a15..9241025 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -297,7 +297,7 @@ struct musb { irqreturn_t (*isr)(int, void *); struct work_struct irq_work; - struct work_struct recover_work; + struct delayed_work recover_work; struct delayed_work deassert_reset_work; struct delayed_work finish_resume_work; u16 hwvers; -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 5/6] usb: musb: dsps: Add the sw_babble_control()
Add sw_babble_control() logic to differentiate between transient babble and real babble condition. Also add the SW babble control register definitions. Babble control register logic is implemented in the latest revision of AM335x. Signed-off-by: George Cherian --- drivers/usb/musb/musb_dsps.c | 50 drivers/usb/musb/musb_regs.h | 7 +++ 2 files changed, 57 insertions(+) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index f6f3087..868caf8 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -536,6 +536,56 @@ static int dsps_musb_set_mode(struct musb *musb, u8 mode) return 0; } +static int sw_babble_control(struct musb *musb) +{ + int timeout = 10; + u8 babble_ctl, session_restart = 0; + + babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); + dev_dbg(musb->controller, "babble: MUSB_BABBLE_CTL value %x\n", + babble_ctl); + /* +* check line monitor flag to check whether babble is +* due to noise +*/ + dev_dbg(musb->controller, "STUCK_J is %s\n", + babble_ctl & MUSB_BABBLE_STUCK_J ? "set" : "reset"); + + if (babble_ctl & MUSB_BABBLE_STUCK_J) { + /* +* babble is due to noise, then set transmit idle (d7 bit) +* to resume normal operation +*/ + babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); + babble_ctl |= MUSB_BABBLE_FORCE_TXIDLE; + dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, babble_ctl); + + /* wait till line monitor flag cleared */ + dev_dbg(musb->controller, "Set TXIDLE, wait J to clear\n"); + do { + babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); + udelay(1); + } while ((babble_ctl & MUSB_BABBLE_STUCK_J) && timeout--); + + /* check whether stuck_at_j bit cleared */ + if (babble_ctl & MUSB_BABBLE_STUCK_J) { + /* +* real babble condition is occured +* restart the controller to start the +* session again +*/ + dev_dbg(musb->controller, "J not cleared, misc (%x)\n", + babble_ctl); + session_restart = 1; + } + + } else { + session_restart = 1; + } + + return session_restart; +} + static int dsps_musb_reset(struct musb *musb) { struct device *dev = musb->controller; diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h index 03f2655..b9bcda5 100644 --- a/drivers/usb/musb/musb_regs.h +++ b/drivers/usb/musb/musb_regs.h @@ -72,6 +72,12 @@ #define MUSB_DEVCTL_HR 0x02 #define MUSB_DEVCTL_SESSION0x01 +/* BABBLE_CTL */ +#define MUSB_BABBLE_FORCE_TXIDLE 0x80 +#define MUSB_BABBLE_SW_SESSION_CTRL0x40 +#define MUSB_BABBLE_STUCK_J0x20 +#define MUSB_BABBLE_RCV_DISABLE0x04 + /* MUSB ULPI VBUSCONTROL */ #define MUSB_ULPI_USE_EXTVBUS 0x01 #define MUSB_ULPI_USE_EXTVBUSIND 0x02 @@ -246,6 +252,7 @@ */ #define MUSB_DEVCTL0x60/* 8 bit */ +#define MUSB_BABBLE_CTL0x61/* 8 bit */ /* These are always controlled through the INDEX register */ #define MUSB_TXFIFOSZ 0x62/* 8-bit (see masks) */ -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 6/6] usb: musb: dsps: Enable sw babble control for newer silicon
Find whether we are running on newer silicon. The babble control register reads 0x4 by default in newer silicon as opposed to 0 in old versions of AM335x. Based on this enable the sw babble control logic. Signed-off-by: George Cherian --- drivers/usb/musb/musb_dsps.c | 38 -- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 868caf8..2ced061 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -136,6 +136,7 @@ struct dsps_glue { const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */ struct timer_list timer;/* otg_workaround timer */ unsigned long last_timer;/* last timer data for each instance */ + bool sw_babble_enabled; struct dsps_context context; struct debugfs_regset32 regset; @@ -469,6 +470,19 @@ static int dsps_musb_init(struct musb *musb) val &= ~(1 << wrp->otg_disable); dsps_writel(musb->ctrl_base, wrp->phy_utmi, val); + /* +* Check whether the dsps version has babble control enabled. +* In latest silicon revision the babble control logic is enabled. +* If MUSB_BABBLE_CTL returns 0x4 then we have the babble control +* logic enabled. +*/ + val = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); + if (val == MUSB_BABBLE_RCV_DISABLE) { + glue->sw_babble_enabled = true; + val |= MUSB_BABBLE_SW_SESSION_CTRL; + dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, val); + } + ret = dsps_musb_dbg_init(musb, glue); if (ret) return ret; @@ -591,14 +605,26 @@ static int dsps_musb_reset(struct musb *musb) struct device *dev = musb->controller; struct dsps_glue *glue = dev_get_drvdata(dev->parent); const struct dsps_musb_wrapper *wrp = glue->wrp; + int session_restart = 0; - dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset)); - usleep_range(100, 200); - usb_phy_shutdown(musb->xceiv); - usleep_range(100, 200); - usb_phy_init(musb->xceiv); + if (glue->sw_babble_enabled) + session_restart = sw_babble_control(musb); + /* +* In case of new silicon version babble condition can be recovered +* without resetting the MUSB. But for older silicon versions, MUSB +* reset is needed +*/ + if (session_restart || !glue->sw_babble_enabled) { + dev_info(musb->controller, "Restarting MUSB to recover from Babble\n"); + dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset)); + usleep_range(100, 200); + usb_phy_shutdown(musb->xceiv); + usleep_range(100, 200); + usb_phy_init(musb->xceiv); + session_restart = 1; + } - return 0; + return !session_restart; } static struct musb_platform_ops dsps_ops = { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 4/6] usb: musb: core: Convert the musb_platform_reset to have a return value.
Currently musb_platform_reset() is only used by dsps. In case of BABBLE interrupt for other platforms the musb_platform_reset() is a NOP. In such situations no need to re-initialize the endpoints. Also in the latest silicon revision of AM335x, we do have a babble recovery mechanism without resetting the IP block. In preperation to add that support its better to have a rest_done return for musb_platform_reset(). Signed-off-by: George Cherian --- drivers/usb/musb/musb_core.c | 10 ++ drivers/usb/musb/musb_core.h | 10 ++ drivers/usb/musb/musb_dsps.c | 3 ++- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 8920b80..7c6836cc 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1755,9 +1755,11 @@ static void musb_irq_work(struct work_struct *data) static void musb_recover_work(struct work_struct *data) { struct musb *musb = container_of(data, struct musb, recover_work.work); - int status; + int status, ret; - musb_platform_reset(musb); + ret = musb_platform_reset(musb); + if (ret) + return; usb_phy_vbus_off(musb->xceiv); usleep_range(100, 200); @@ -1766,8 +1768,8 @@ static void musb_recover_work(struct work_struct *data) usleep_range(100, 200); /* -* When a babble condition occurs, the musb controller removes the -* session bit and the endpoint config is lost. +* When a babble condition occurs, the musb controller +* removes the session bit and the endpoint config is lost. */ if (musb->dyn_fifo) status = ep_config_from_table(musb); diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 9241025..414e57a 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -192,7 +192,7 @@ struct musb_platform_ops { int (*set_mode)(struct musb *musb, u8 mode); void(*try_idle)(struct musb *musb, unsigned long timeout); - void(*reset)(struct musb *musb); + int (*reset)(struct musb *musb); int (*vbus_status)(struct musb *musb); void(*set_vbus)(struct musb *musb, int on); @@ -555,10 +555,12 @@ static inline void musb_platform_try_idle(struct musb *musb, musb->ops->try_idle(musb, timeout); } -static inline void musb_platform_reset(struct musb *musb) +static inline int musb_platform_reset(struct musb *musb) { - if (musb->ops->reset) - musb->ops->reset(musb); + if (!musb->ops->reset) + return -EINVAL; + + return musb->ops->reset(musb); } static inline int musb_platform_get_vbus_status(struct musb *musb) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 74c4193..f6f3087 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -536,7 +536,7 @@ static int dsps_musb_set_mode(struct musb *musb, u8 mode) return 0; } -static void dsps_musb_reset(struct musb *musb) +static int dsps_musb_reset(struct musb *musb) { struct device *dev = musb->controller; struct dsps_glue *glue = dev_get_drvdata(dev->parent); @@ -548,6 +548,7 @@ static void dsps_musb_reset(struct musb *musb) usleep_range(100, 200); usb_phy_init(musb->xceiv); + return 0; } static struct musb_platform_ops dsps_ops = { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 3/6] usb: musb: dsps: Call usb_phy(_shutdown/_init) during musb_platform_reset()
For DSPS platform usb_phy_vbus(_off/_on) are NOPs. So during musb_platform_reset() call usb_phy(_shutdown/_init) Signed-off-by: George Cherian --- drivers/usb/musb/musb_dsps.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 51beb13..74c4193 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -543,7 +543,11 @@ static void dsps_musb_reset(struct musb *musb) const struct dsps_musb_wrapper *wrp = glue->wrp; dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset)); - udelay(100); + usleep_range(100, 200); + usb_phy_shutdown(musb->xceiv); + usleep_range(100, 200); + usb_phy_init(musb->xceiv); + } static struct musb_platform_ops dsps_ops = { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v5 1/6] usb: musb: core: Handle Babble condition only in HOST mode
BABBLE and RESET share the same interrupt. The interrupt is considered to be RESET if MUSB is in peripheral mode and as a BABBLE if MUSB is in HOST mode. Handle babble condition iff MUSB is in HOST mode. Signed-off-by: George Cherian --- drivers/usb/musb/musb_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 61da471..eff3c5c 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -849,7 +849,7 @@ b_host: } /* handle babble condition */ - if (int_usb & MUSB_INTR_BABBLE) + if (int_usb & MUSB_INTR_BABBLE && is_host_active(musb)) schedule_work(&musb->recover_work); #if 0 -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 1/6] usb: dwc3: dwc3-omap: Remove x_major calculation from revision register
Remove the x_major calculation logic from the wrapper revision register to differentiate between OMAP5 and AM437x. This was done to find the register offsets of wrapper register. Now that We do it using dt compatible, remove the whole logic. Signed-off-by: George Cherian --- drivers/usb/dwc3/dwc3-omap.c | 36 1 file changed, 4 insertions(+), 32 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 4af4c35..999bdc8 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -77,10 +77,6 @@ #define USBOTGSS_DEV_EBC_EN0x0110 #define USBOTGSS_DEBUG_OFFSET 0x0600 -/* REVISION REGISTER */ -#define USBOTGSS_REVISION_XMAJOR(reg) ((reg >> 8) & 0x7) -#define USBOTGSS_REVISION_XMAJOR1 1 -#define USBOTGSS_REVISION_XMAJOR2 2 /* SYSCONFIG REGISTER */ #define USBOTGSS_SYSCONFIG_DMADISABLE (1 << 16) @@ -129,7 +125,6 @@ struct dwc3_omap { u32 irq_eoi_offset; u32 debug_offset; u32 irq0_offset; - u32 revision; u32 dma_status:1; @@ -397,7 +392,6 @@ static int dwc3_omap_probe(struct platform_device *pdev) int irq; int utmi_mode = 0; - int x_major; u32 reg; @@ -448,32 +442,10 @@ static int dwc3_omap_probe(struct platform_device *pdev) goto err0; } - reg = dwc3_omap_readl(omap->base, USBOTGSS_REVISION); - omap->revision = reg; - x_major = USBOTGSS_REVISION_XMAJOR(reg); - - /* Differentiate between OMAP5 and AM437x */ - switch (x_major) { - case USBOTGSS_REVISION_XMAJOR1: - case USBOTGSS_REVISION_XMAJOR2: - omap->irq_eoi_offset = 0; - omap->irq0_offset = 0; - omap->irqmisc_offset = 0; - omap->utmi_otg_offset = 0; - omap->debug_offset = 0; - break; - default: - /* Default to the latest revision */ - omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET; - omap->irq0_offset = USBOTGSS_IRQ0_OFFSET; - omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET; - omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET; - omap->debug_offset = USBOTGSS_DEBUG_OFFSET; - break; - } - - /* For OMAP5(ES2.0) and AM437x x_major is 2 even though there are -* changes in wrapper registers, Using dt compatible for aegis + /* Differentiate between OMAP5 and AM437x. +* For OMAP5(ES2.0) and AM437x wrapper revision is same, even +* though there are changes in wrapper register offsets. +* Using dt compatible to differentiate AM437x. */ if (of_device_is_compatible(node, "ti,am437x-dwc3")) { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 4/6] usb: dwc3: dwc3-omap: Add dwc3_omap_extcon_register function
Move the extcon related code to its own function. Improve code readability, decrease the dwc3_probe() size. Signed-off-by: George Cherian --- drivers/usb/dwc3/dwc3-omap.c | 65 ++-- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 56ec6eb..7594535 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -421,6 +421,42 @@ static void dwc3_omap_set_utmi_mode(struct dwc3_omap *omap) dwc3_omap_write_utmi_status(omap, reg); } +static int dwc3_omap_extcon_register(struct dwc3_omap *omap) +{ + u32 ret; + struct device_node *node = omap->dev->of_node; + struct extcon_dev *edev; + + if (of_property_read_bool(node, "extcon")) { + edev = extcon_get_edev_by_phandle(omap->dev, 0); + if (IS_ERR(edev)) { + dev_vdbg(omap->dev, "couldn't get extcon device\n"); + return -EPROBE_DEFER; + } + + omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier; + ret = extcon_register_interest(&omap->extcon_vbus_dev, + edev->name, "USB", + &omap->vbus_nb); + if (ret < 0) + dev_vdbg(omap->dev, "failed to register notifier for USB\n"); + + omap->id_nb.notifier_call = dwc3_omap_id_notifier; + ret = extcon_register_interest(&omap->extcon_id_dev, + edev->name, "USB-HOST", + &omap->id_nb); + if (ret < 0) + dev_vdbg(omap->dev, "failed to register notifier for USB-HOST\n"); + + if (extcon_get_cable_state(edev, "USB") == true) + dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID); + if (extcon_get_cable_state(edev, "USB-HOST") == true) + dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND); + } + + return 0; +} + static int dwc3_omap_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -428,7 +464,6 @@ static int dwc3_omap_probe(struct platform_device *pdev) struct dwc3_omap*omap; struct resource *res; struct device *dev = &pdev->dev; - struct extcon_dev *edev; struct regulator*vbus_reg = NULL; int ret; @@ -500,31 +535,9 @@ static int dwc3_omap_probe(struct platform_device *pdev) dwc3_omap_enable_irqs(omap); - if (of_property_read_bool(node, "extcon")) { - edev = extcon_get_edev_by_phandle(dev, 0); - if (IS_ERR(edev)) { - dev_vdbg(dev, "couldn't get extcon device\n"); - ret = -EPROBE_DEFER; - goto err2; - } - - omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier; - ret = extcon_register_interest(&omap->extcon_vbus_dev, - edev->name, "USB", &omap->vbus_nb); - if (ret < 0) - dev_vdbg(dev, "failed to register notifier for USB\n"); - omap->id_nb.notifier_call = dwc3_omap_id_notifier; - ret = extcon_register_interest(&omap->extcon_id_dev, edev->name, -"USB-HOST", &omap->id_nb); - if (ret < 0) - dev_vdbg(dev, - "failed to register notifier for USB-HOST\n"); - - if (extcon_get_cable_state(edev, "USB") == true) - dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID); - if (extcon_get_cable_state(edev, "USB-HOST") == true) - dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND); - } + ret = dwc3_omap_extcon_register(omap); + if (ret < 0) + goto err2; ret = of_platform_populate(node, NULL, NULL, dev); if (ret) { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 5/6] usb: dwc3: dwc3-omap: Fix the crash on module removal
Following crash is seen on dwc3_omap removal Unable to handle kernel NULL pointer dereference at virtual address 0018 pgd = ec098000 [0018] *pgd=ad1f9831, *pte=, *ppte= Internal error: Oops: 17 [#1] SMP ARM Modules linked in: usb_f_ss_lb g_zero usb_f_acm u_serial usb_f_ecm u_ether libcomposite configfs snd_usb_audio snd_usbmidi_lib snd_rawmidi snd_hwdep snd_soc_omap snd_pcm_dmaengine snd_soc_core snd_compress snd_pcm snd_tim] CPU: 0 PID: 1296 Comm: rmmod Tainted: GW 3.15.0-rc4-02716-g95c4e18-dirty #10 task: ed05a080 ti: ec368000 task.ti: ec368000 PC is at release_resource+0x14/0x7c LR is at release_resource+0x10/0x7c pc : []lr : []psr: 6013 sp : ec369ec0 ip : 6013 fp : 00021008 r10: r9 : ec368000 r8 : c000e7a4 r7 : 0081 r6 : bf0062c0 r5 : ed7cd000 r4 : ed7d85c0 r3 : r2 : r1 : 0011 r0 : c086d08c Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user Control: 10c5387d Table: ac098059 DAC: 0015 Process rmmod (pid: 1296, stack limit = 0xec368248) Stack: (0xec369ec0 to 0xec36a000) 9ec0: 0001 ed7cd000 c034de94 ed7cd010 ed7cd000 c034e194 9ee0: bf0062cc ed7cd010 c03490b0 ed154cc0 ed4c2570 ed2b8410 ed156810 ed156810 bf006d24 c034db9c c034db84 c034c518 9f20: bf006d24 ed156810 bf006d24 c034cd2c bf006d24 bf006d68 0800 c034c340 9f40: c00a9e5c 0020 bf006d68 0800 ec369f4c 33637764 9f60: 616d6f5f 0070 0001 ec368000 ed05a080 c000e670 0001 c0084010 9f80: 00021088 0800 00021088 0081 8010 e6f4 00021088 0800 9fa0: 00021088 c000e5e0 00021088 0800 000210b8 0800 e04f6d00 e04f6d00 9fc0: 00021088 0800 00021088 0081 0001 be91de08 00021008 9fe0: 4d768880 be91dbb4 b6fc5984 4d76888c 8010 000210b8 [] (release_resource) from [] (platform_device_del+0x6c/0x9c) [] (platform_device_del) from [] (platform_device_unregister+0xc/0x18) [] (platform_device_unregister) from [] (dwc3_omap_remove_core+0xc/0x14 [dwc3_omap]) [] (dwc3_omap_remove_core [dwc3_omap]) from [] (device_for_each_child+0x34/0x74) [] (device_for_each_child) from [] (dwc3_omap_remove+0x6c/0x78 [dwc3_omap]) [] (dwc3_omap_remove [dwc3_omap]) from [] (platform_drv_remove+0x18/0x1c) [] (platform_drv_remove) from [] (__device_release_driver+0x70/0xc8) [] (__device_release_driver) from [] (driver_detach+0xb4/0xb8) [] (driver_detach) from [] (bus_remove_driver+0x4c/0x90) [] (bus_remove_driver) from [] (SyS_delete_module+0x10c/0x198) [] (SyS_delete_module) from [] (ret_fast_syscall+0x0/0x48) Code: e1a04000 e59f0068 eb14505e e5943010 (e5932018) ---[ end trace 7e2a8746ff4fc811 ]--- Segmentation fault Signed-off-by: George Cherian --- drivers/usb/dwc3/dwc3-omap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 7594535..b729cdb 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -317,7 +317,7 @@ static int dwc3_omap_remove_core(struct device *dev, void *c) { struct platform_device *pdev = to_platform_device(dev); - platform_device_unregister(pdev); + of_device_unregister(pdev); return 0; } -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 6/6] usb: dwc3: dwc3-omap: Disable/Enable only wrapper interrupts in prepare/complete
The dwc3 wrapper driver should not be fiddling with the core interrupts. Disabling the core interrupts in prepare stops xhci from proper operation. So remove disable/enable of core interrupts from prepare/complete. Signed-off-by: George Cherian --- drivers/usb/dwc3/dwc3-omap.c | 15 +-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index b729cdb..116f71c 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -597,7 +597,7 @@ static int dwc3_omap_prepare(struct device *dev) { struct dwc3_omap*omap = dev_get_drvdata(dev); - dwc3_omap_disable_irqs(omap); + dwc3_omap_write_irqmisc_set(omap, 0x00); return 0; } @@ -605,8 +605,19 @@ static int dwc3_omap_prepare(struct device *dev) static void dwc3_omap_complete(struct device *dev) { struct dwc3_omap*omap = dev_get_drvdata(dev); + u32 reg; - dwc3_omap_enable_irqs(omap); + reg = (USBOTGSS_IRQMISC_OEVT | + USBOTGSS_IRQMISC_DRVVBUS_RISE | + USBOTGSS_IRQMISC_CHRGVBUS_RISE | + USBOTGSS_IRQMISC_DISCHRGVBUS_RISE | + USBOTGSS_IRQMISC_IDPULLUP_RISE | + USBOTGSS_IRQMISC_DRVVBUS_FALL | + USBOTGSS_IRQMISC_CHRGVBUS_FALL | + USBOTGSS_IRQMISC_DISCHRGVBUS_FALL | + USBOTGSS_IRQMISC_IDPULLUP_FALL); + + dwc3_omap_write_irqmisc_set(omap, reg); } static int dwc3_omap_suspend(struct device *dev) -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 3/6] usb: dwc3: dwc3-omap: Add dwc3_omap_set_utmi_mode() function
Move find and set the utmi mode to its own seperate function. Improve code readability, decrease the dwc3_probe() size. Signed-off-by: George Cherian --- drivers/usb/dwc3/dwc3-omap.c | 44 +--- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 09918ac..56ec6eb 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -397,6 +397,30 @@ static void dwc3_omap_map_offset(struct dwc3_omap *omap) } } +static void dwc3_omap_set_utmi_mode(struct dwc3_omap *omap) +{ + u32 reg; + struct device_node *node = omap->dev->of_node; + int utmi_mode = 0; + + reg = dwc3_omap_read_utmi_status(omap); + + of_property_read_u32(node, "utmi-mode", &utmi_mode); + + switch (utmi_mode) { + case DWC3_OMAP_UTMI_MODE_SW: + reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE; + break; + case DWC3_OMAP_UTMI_MODE_HW: + reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE; + break; + default: + dev_dbg(omap->dev, "UNKNOWN utmi mode %d\n", utmi_mode); + } + + dwc3_omap_write_utmi_status(omap, reg); +} + static int dwc3_omap_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -410,8 +434,6 @@ static int dwc3_omap_probe(struct platform_device *pdev) int ret; int irq; - int utmi_mode = 0; - u32 reg; void __iomem*base; @@ -462,23 +484,7 @@ static int dwc3_omap_probe(struct platform_device *pdev) } dwc3_omap_map_offset(omap); - - reg = dwc3_omap_read_utmi_status(omap); - - of_property_read_u32(node, "utmi-mode", &utmi_mode); - - switch (utmi_mode) { - case DWC3_OMAP_UTMI_MODE_SW: - reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE; - break; - case DWC3_OMAP_UTMI_MODE_HW: - reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE; - break; - default: - dev_dbg(dev, "UNKNOWN utmi mode %d\n", utmi_mode); - } - - dwc3_omap_write_utmi_status(omap, reg); + dwc3_omap_set_utmi_mode(omap); /* check the DMA Status */ reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG); -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 2/6] usb: dwc3: dwc3-omap: Add dwc3_omap_map_offset() function
Move map offset to its own seperate function. Improve code readability, decrease the dwc3_probe() size. Signed-off-by: George Cherian --- drivers/usb/dwc3/dwc3-omap.c | 33 - 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 999bdc8..09918ac 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -378,6 +378,25 @@ static int dwc3_omap_vbus_notifier(struct notifier_block *nb, return NOTIFY_DONE; } +static void dwc3_omap_map_offset(struct dwc3_omap *omap) +{ + struct device_node *node = omap->dev->of_node; + + /* Differentiate between OMAP5 and AM437x. +* For OMAP5(ES2.0) and AM437x wrapper revision is same even +* though there are changes in wrapper register offsets. +* Using dt compatible to differentiate AM437x. +*/ + + if (of_device_is_compatible(node, "ti,am437x-dwc3")) { + omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET; + omap->irq0_offset = USBOTGSS_IRQ0_OFFSET; + omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET; + omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET; + omap->debug_offset = USBOTGSS_DEBUG_OFFSET; + } +} + static int dwc3_omap_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -442,19 +461,7 @@ static int dwc3_omap_probe(struct platform_device *pdev) goto err0; } - /* Differentiate between OMAP5 and AM437x. -* For OMAP5(ES2.0) and AM437x wrapper revision is same, even -* though there are changes in wrapper register offsets. -* Using dt compatible to differentiate AM437x. -*/ - - if (of_device_is_compatible(node, "ti,am437x-dwc3")) { - omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET; - omap->irq0_offset = USBOTGSS_IRQ0_OFFSET; - omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET; - omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET; - omap->debug_offset = USBOTGSS_DEBUG_OFFSET; - } + dwc3_omap_map_offset(omap); reg = dwc3_omap_read_utmi_status(omap); -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 0/6] Cleanup and fixes for dwc3-omap
The series does some refactoring on dwc3_probe() Patch 1 - Now that we use driver compatible for revision check, remove the unnecessary logic. Patch 2-4 - reduce the size of dwc3_probe() Patch 5 - Fix the crash on dwc3_omap removal Patch 6 - Addresses the issue of xhci hang while resuming from system sleep. George Cherian (6): usb: dwc3: dwc3-omap: Remove x_major calculation from revision register usb: dwc3: dwc3-omap: Add dwc3_omap_map_offset() function usb: dwc3: dwc3-omap: Add dwc3_omap_set_utmi_mode() function usb: dwc3: dwc3-omap: Add dwc3_omap_extcon_register function usb: dwc3: dwc3-omap: Fix the crash on module removal usb: dwc3: dwc3-omap: Disable/Enable only wrapper interrupts in prepare/complete drivers/usb/dwc3/dwc3-omap.c | 187 +++ 1 file changed, 98 insertions(+), 89 deletions(-) -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 1/6] usb: musb: core: Handle Babble condition only in HOST mode
Hi Bin, On 5/19/2014 9:24 PM, Bin Liu wrote: Hi, On Mon, May 19, 2014 at 8:39 AM, George Cherian wrote: BABBLE and RESET share the same interrupt. The interrupt is considered to be RESET if MUSB is in peripheral mode and as a BABBLE if MUSB is in HOST mode. Handle babble condition iff MUSB is in HOST mode. Signed-off-by: George Cherian --- drivers/usb/musb/musb_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 61da471..eff3c5c 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -849,7 +849,7 @@ b_host: } /* handle babble condition */ - if (int_usb & MUSB_INTR_BABBLE) + if (int_usb & MUSB_INTR_BABBLE && is_host_active(musb)) schedule_work(&musb->recover_work); I guess my following comments are for Daniel's patch as while which initially added the babble work. Should this if statement be merged into the previous 'if(int_usb & MUSB_INTR_RESET)' one, which handles the same interrupt and already handles host and device mode respectively. Initially I too had the babble handling as part of 'if(int_usb & MUSB_INTR_RESET)' one. But during my tests I hit a corner case where in we hit a BABBLE condition on disconnect. In such case the babble interrupt can be handled only if we have a seperate check, else its considered as a BUS RESET. When all devices are disconnected MUSB_DEVCTL_HM = 0 and the code always enter the else path. In this path it treats the BABBLE as a BUS RESET. Regards, -Bin. #if 0 -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- -George -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 1/6] usb: musb: core: Handle Babble condition only in HOST mode
BABBLE and RESET share the same interrupt. The interrupt is considered to be RESET if MUSB is in peripheral mode and as a BABBLE if MUSB is in HOST mode. Handle babble condition iff MUSB is in HOST mode. Signed-off-by: George Cherian --- drivers/usb/musb/musb_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 61da471..eff3c5c 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -849,7 +849,7 @@ b_host: } /* handle babble condition */ - if (int_usb & MUSB_INTR_BABBLE) + if (int_usb & MUSB_INTR_BABBLE && is_host_active(musb)) schedule_work(&musb->recover_work); #if 0 -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 5/6] usb: musb: dsps: Add the sw_babble_control()
Add sw_babble_control() logic to differentiate between transient babble and real babble condition. Also add the SW babble control register definitions. Babble control register logic is implemented in the latest revision of AM335x. Signed-off-by: George Cherian --- drivers/usb/musb/musb_dsps.c | 50 drivers/usb/musb/musb_regs.h | 7 +++ 2 files changed, 57 insertions(+) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index f6f3087..eb1985a 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -536,6 +536,56 @@ static int dsps_musb_set_mode(struct musb *musb, u8 mode) return 0; } +static int sw_babble_control(struct musb *musb) +{ + int timeout = 10; + u8 babble_ctl, session_restart = 0; + + babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); + dev_dbg(musb->controller, "babble: MUSB_BABBLE_CTL value %x\n", + babble_ctl); + /* +* check line monitor flag to check whether babble is +* due to noise +*/ + dev_dbg(musb->controller, "STUCK_J is %s\n", + babble_ctl & MUSB_BABBLE_STUCK_J ? "set" : "reset"); + + if (babble_ctl & MUSB_BABBLE_STUCK_J) { + /* +* babble is due to noise, then set transmit idle (d7 bit) +* to resume normal operation +*/ + babble_ctl = musb_readb(musb->mregs, MUSB_BABBLE_CTL); + babble_ctl |= MUSB_BABBLE_FORCE_TXIDLE; + dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, babble_ctl); + + /* wait till line monitor flag cleared */ + dev_dbg(musb->controller, "Set TXIDLE, wait J to clear\n"); + do { + babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); + udelay(1); + } while ((babble_ctl & MUSB_BABBLE_STUCK_J) && timeout--); + + /* check whether stuck_at_j bit cleared */ + if (babble_ctl & MUSB_BABBLE_STUCK_J) { + /* +* real babble condition is occured +* restart the controller to start the +* session again +*/ + dev_dbg(musb->controller, "J not cleared, misc (%x)\n", + babble_ctl); + session_restart = 1; + } + + } else { + session_restart = 1; + } + + return session_restart; +} + static int dsps_musb_reset(struct musb *musb) { struct device *dev = musb->controller; diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h index 03f2655..b9bcda5 100644 --- a/drivers/usb/musb/musb_regs.h +++ b/drivers/usb/musb/musb_regs.h @@ -72,6 +72,12 @@ #define MUSB_DEVCTL_HR 0x02 #define MUSB_DEVCTL_SESSION0x01 +/* BABBLE_CTL */ +#define MUSB_BABBLE_FORCE_TXIDLE 0x80 +#define MUSB_BABBLE_SW_SESSION_CTRL0x40 +#define MUSB_BABBLE_STUCK_J0x20 +#define MUSB_BABBLE_RCV_DISABLE0x04 + /* MUSB ULPI VBUSCONTROL */ #define MUSB_ULPI_USE_EXTVBUS 0x01 #define MUSB_ULPI_USE_EXTVBUSIND 0x02 @@ -246,6 +252,7 @@ */ #define MUSB_DEVCTL0x60/* 8 bit */ +#define MUSB_BABBLE_CTL0x61/* 8 bit */ /* These are always controlled through the INDEX register */ #define MUSB_TXFIFOSZ 0x62/* 8-bit (see masks) */ -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 4/6] usb: musb: core: Convert the musb_platform_reset to have a return value.
Currently musb_platform_reset() is only used by dsps. In case of BABBLE interrupt for other platforms the musb_platform_reset() is a NOP. In such situations no need to re-initialize the endpoints. Also in the latest silicon revision of AM335x, we do have a babble recovery mechanism without resetting the IP block. In preperation to add that support its better to have a rest_done return for musb_platform_reset(). Signed-off-by: George Cherian --- drivers/usb/musb/musb_core.c | 38 +- drivers/usb/musb/musb_core.h | 10 ++ drivers/usb/musb/musb_dsps.c | 3 ++- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 8920b80..1b0b85d 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1755,28 +1755,32 @@ static void musb_irq_work(struct work_struct *data) static void musb_recover_work(struct work_struct *data) { struct musb *musb = container_of(data, struct musb, recover_work.work); - int status; + int status, ret; - musb_platform_reset(musb); + ret = musb_platform_reset(musb); + if (ret < 0) + return; - usb_phy_vbus_off(musb->xceiv); - usleep_range(100, 200); + if (!ret) { + usb_phy_vbus_off(musb->xceiv); + usleep_range(100, 200); - usb_phy_vbus_on(musb->xceiv); - usleep_range(100, 200); + usb_phy_vbus_on(musb->xceiv); + usleep_range(100, 200); - /* -* When a babble condition occurs, the musb controller removes the -* session bit and the endpoint config is lost. -*/ - if (musb->dyn_fifo) - status = ep_config_from_table(musb); - else - status = ep_config_from_hw(musb); + /* +* When a babble condition occurs, the musb controller +* removes the session bit and the endpoint config is lost. +*/ + if (musb->dyn_fifo) + status = ep_config_from_table(musb); + else + status = ep_config_from_hw(musb); - /* start the session again */ - if (status == 0) - musb_start(musb); + /* start the session again */ + if (status == 0) + musb_start(musb); + } } /* -- diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 423cd00..3ccb428 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -192,7 +192,7 @@ struct musb_platform_ops { int (*set_mode)(struct musb *musb, u8 mode); void(*try_idle)(struct musb *musb, unsigned long timeout); - void(*reset)(struct musb *musb); + int (*reset)(struct musb *musb); int (*vbus_status)(struct musb *musb); void(*set_vbus)(struct musb *musb, int on); @@ -554,10 +554,12 @@ static inline void musb_platform_try_idle(struct musb *musb, musb->ops->try_idle(musb, timeout); } -static inline void musb_platform_reset(struct musb *musb) +static inline int musb_platform_reset(struct musb *musb) { - if (musb->ops->reset) - musb->ops->reset(musb); + if (!musb->ops->reset) + return -EINVAL; + + return musb->ops->reset(musb); } static inline int musb_platform_get_vbus_status(struct musb *musb) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 74c4193..f6f3087 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -536,7 +536,7 @@ static int dsps_musb_set_mode(struct musb *musb, u8 mode) return 0; } -static void dsps_musb_reset(struct musb *musb) +static int dsps_musb_reset(struct musb *musb) { struct device *dev = musb->controller; struct dsps_glue *glue = dev_get_drvdata(dev->parent); @@ -548,6 +548,7 @@ static void dsps_musb_reset(struct musb *musb) usleep_range(100, 200); usb_phy_init(musb->xceiv); + return 0; } static struct musb_platform_ops dsps_ops = { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 3/6] usb: musb: dsps: Call usb_phy(_shutdown/_init) during musb_platform_reset()
For DSPS platform usb_phy_vbus(_off/_on) are NOPs. So during musb_platform_reset() call usb_phy(_shutdown/_init) Signed-off-by: George Cherian --- drivers/usb/musb/musb_dsps.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 51beb13..74c4193 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -543,7 +543,11 @@ static void dsps_musb_reset(struct musb *musb) const struct dsps_musb_wrapper *wrp = glue->wrp; dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset)); - udelay(100); + usleep_range(100, 200); + usb_phy_shutdown(musb->xceiv); + usleep_range(100, 200); + usb_phy_init(musb->xceiv); + } static struct musb_platform_ops dsps_ops = { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 2/6] usb: musb: core: Convert babble recover work to delayed work
During babble condition both first disconnect of devices are initiated. Make sure MUSB controller is reset and re-initialized after all disconnects. To acheive this schedule a delayed work for babble rrecovery. While at that convert udelay to usleep_range. Refer Documentation/timers/timers-howto.txt Signed-off-by: George Cherian --- drivers/usb/musb/musb_core.c | 15 --- drivers/usb/musb/musb_core.h | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index eff3c5c..8920b80 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -850,7 +850,8 @@ b_host: /* handle babble condition */ if (int_usb & MUSB_INTR_BABBLE && is_host_active(musb)) - schedule_work(&musb->recover_work); + schedule_delayed_work(&musb->recover_work, + msecs_to_jiffies(100)); #if 0 /* REVISIT ... this would be for multiplexing periodic endpoints, or @@ -1753,16 +1754,16 @@ static void musb_irq_work(struct work_struct *data) /* Recover from babble interrupt conditions */ static void musb_recover_work(struct work_struct *data) { - struct musb *musb = container_of(data, struct musb, recover_work); + struct musb *musb = container_of(data, struct musb, recover_work.work); int status; musb_platform_reset(musb); usb_phy_vbus_off(musb->xceiv); - udelay(100); + usleep_range(100, 200); usb_phy_vbus_on(musb->xceiv); - udelay(100); + usleep_range(100, 200); /* * When a babble condition occurs, the musb controller removes the @@ -1945,7 +1946,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) /* Init IRQ workqueue before request_irq */ INIT_WORK(&musb->irq_work, musb_irq_work); - INIT_WORK(&musb->recover_work, musb_recover_work); + INIT_DELAYED_WORK(&musb->recover_work, musb_recover_work); INIT_DELAYED_WORK(&musb->deassert_reset_work, musb_deassert_reset); INIT_DELAYED_WORK(&musb->finish_resume_work, musb_host_finish_resume); @@ -2041,7 +2042,7 @@ fail4: fail3: cancel_work_sync(&musb->irq_work); - cancel_work_sync(&musb->recover_work); + cancel_delayed_work_sync(&musb->recover_work); cancel_delayed_work_sync(&musb->finish_resume_work); cancel_delayed_work_sync(&musb->deassert_reset_work); if (musb->dma_controller) @@ -2107,7 +2108,7 @@ static int musb_remove(struct platform_device *pdev) dma_controller_destroy(musb->dma_controller); cancel_work_sync(&musb->irq_work); - cancel_work_sync(&musb->recover_work); + cancel_delayed_work_sync(&musb->recover_work); cancel_delayed_work_sync(&musb->finish_resume_work); cancel_delayed_work_sync(&musb->deassert_reset_work); musb_free(musb); diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 47e8874..423cd00 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -297,7 +297,7 @@ struct musb { irqreturn_t (*isr)(int, void *); struct work_struct irq_work; - struct work_struct recover_work; + struct delayed_work recover_work; struct delayed_work deassert_reset_work; struct delayed_work finish_resume_work; u16 hwvers; -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 6/6] usb: musb: dsps: Enable sw babble control for newer silicon
Find whether we are running on newer silicon. The babble control register reads 0x4 by default in newer silicon as opposed to 0 in old versions of AM335x. Based on this enable the sw babble control logic. Signed-off-by: George Cherian --- drivers/usb/musb/musb_dsps.c | 37 +++-- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index eb1985a..8daccb2 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -136,6 +136,7 @@ struct dsps_glue { const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */ struct timer_list timer;/* otg_workaround timer */ unsigned long last_timer;/* last timer data for each instance */ + bool sw_babble_enabled; struct dsps_context context; struct debugfs_regset32 regset; @@ -469,6 +470,19 @@ static int dsps_musb_init(struct musb *musb) val &= ~(1 << wrp->otg_disable); dsps_writel(musb->ctrl_base, wrp->phy_utmi, val); + /* +* Check whether the dsps version has babble control enabled. +* In latest silicon revision the babble control logic is enabled. +* If MUSB_BABBLE_CTL returns 0x4 then we have the babble control +* logic enabled. +*/ + val = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); + if (val == MUSB_BABBLE_RCV_DISABLE) { + glue->sw_babble_enabled = true; + val |= MUSB_BABBLE_SW_SESSION_CTRL; + dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, val); + } + ret = dsps_musb_dbg_init(musb, glue); if (ret) return ret; @@ -591,14 +605,25 @@ static int dsps_musb_reset(struct musb *musb) struct device *dev = musb->controller; struct dsps_glue *glue = dev_get_drvdata(dev->parent); const struct dsps_musb_wrapper *wrp = glue->wrp; + int session_restart = 0; - dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset)); - usleep_range(100, 200); - usb_phy_shutdown(musb->xceiv); - usleep_range(100, 200); - usb_phy_init(musb->xceiv); + if (glue->sw_babble_enabled) + session_restart = sw_babble_control(musb); + /* +* In case of new silicon version babble condition can be recovered +* without resetting the MUSB. But for older silicon versions, MUSB +* reset is needed +*/ + if (session_restart || !glue->sw_babble_enabled) { + dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset)); + usleep_range(100, 200); + usb_phy_shutdown(musb->xceiv); + usleep_range(100, 200); + usb_phy_init(musb->xceiv); + session_restart = 1; + } - return 0; + return !session_restart; } static struct musb_platform_ops dsps_ops = { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 0/6] Add support for SW babble Control
Subject: [PATCH v3 0/5] Add support for SW babble Control Series add support for SW babble control logic found in new silicon versions of AM335x. Runtime differentiation of silicon version is done by checking the BABBLE_CTL register. For newer silicon the register default value read is 0x4 and for older versions its 0x0. Patch 1 -> Handle Babble only if MUSB is in HOST mode Patch 2 -> Convert recover work to delayed work. Patch 3 -> usb_phy_vbus_(off/_on) are NOPs for am335x PHY so use usb_phy(_shutdown/_init) in musb_platform_reset() Patch 4 -> Add return value for musb_platform_reset() in prepration to support SW babble_ctrl Patch 5 -> Add the sw_babble_control() Patch 6 -> Enable sw babble control for newer silicon v3 -> v4 : Fixes an issue in gagdet mode - BUS RESET should not be handled as a BABBLE. Added a check for the same.(Patch #1) Enable sw babble control properly (Patch #6) v2 -> v3 : Modify musb_platform_reset() to return zero on success. George Cherian (6): usb: musb: core: Handle Babble condition only in HOST mode usb: musb: core: Convert babble recover work to delayed work usb: musb: dsps: Call usb_phy(_shutdown/_init) during musb_platform_reset() usb: musb: core: Convert the musb_platform_reset to have a return value. usb: musb: dsps: Add the sw_babble_control() usb: musb: dsps: Enable sw babble control for newer silicon drivers/usb/musb/musb_core.c | 51 ++ drivers/usb/musb/musb_core.h | 12 --- drivers/usb/musb/musb_dsps.c | 86 ++-- drivers/usb/musb/musb_regs.h | 7 4 files changed, 125 insertions(+), 31 deletions(-) -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 0/5] Add support for SW babble Control
Hi Bin, On 5/15/2014 8:49 PM, Bin Liu wrote: George, On Thu, May 15, 2014 at 1:28 AM, George Cherian wrote: Hi Bin, On 5/14/2014 10:13 PM, Bin Liu wrote: George, On Wed, May 14, 2014 at 9:34 AM, Bin Liu wrote: George, On Wed, May 14, 2014 at 12:37 AM, George Cherian wrote: On 5/14/2014 12:07 AM, Bin Liu wrote: Hi, On Tue, May 13, 2014 at 8:24 AM, George Cherian wrote: Hi Daniel, On 5/13/2014 6:44 PM, Daniel Mack wrote: Hi George, On 05/13/2014 02:57 PM, George Cherian wrote: I never enabled the MUSB_BABBLE_SW_SESSION_CTRL in the MUSB_BABBLE_CTL reg. can you try with the following patch. diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 1ae6681..1160cd1 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -477,8 +477,11 @@ static int dsps_musb_init(struct musb *musb) * logic enabled. */ val = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); - if (val == MUSB_BABBLE_RCV_DISABLE) + if (val == MUSB_BABBLE_RCV_DISABLE) { glue->sw_babble_enabled = true; + val |= MUSB_BABBLE_SW_SESSION_CTRL; + dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, val); + } ret = dsps_musb_dbg_init(musb, glue); if (ret) MUSB_BABBLE_STUCK_J still remains unset, so I get the same result as without the patch: a full glue reset is conducted. Do I get you right that you expect MUSB_BABBLE_STUCK_J to be set in babble conditions when MUSB_BABBLE_SW_SESSION_CTRL is set? Basically, there are 2 types of babble conditions. 1) Transient babble condition - which could be recovered from without an IP reset . 2) Babble condition - which could be recovered from only by doing an IP reset. Looks like you are always hitting case 2 (Most times am also hitting the same). Case 1 is really hard to reproduce. I don't have a reliable method as of now to reproduce this case consistently. [ 19.672373] CAUTION: musb: Babble Interrupt Occurred [ 19.66] musb_stage0_irq 789: unhandled DISCONNECT transition (a_wait_bcon) [ 19.685815] usb 1-1: USB disconnect, device number 3 [ 19.769720] musb-hdrc musb-hdrc.0.auto: babble: MUSB_BABBLE_CTL value 44 [ 19.776765] musb-hdrc musb-hdrc.0.auto: STUCK_J is reset I don't quite follow, especially as I lack documentation of the IP core. How do you test babble errors, is there any way to force them to happen reliably? There is no 100% reliable method to force it to happen. Following is I have a way to force babble happen reliably - shorting DP or DM to VBUS. I opened the far-end plug of the USB cable, so I can easily short DP or DM to VBUS. Good to know that you have a reliable way to test babble condition. Can you please do a quick test on 3.15.0-rc4 with the series applied? In case of any assistance please do let me know. Sure, but could you please re-send those patches to my corporate email so that I can apply them from Thunderbird? You don't have to resend the patches. Nishanth Menon showed me a way to extract the patch from Gmail - Thanks Nishanth. But which repo do you want to me test with? The first patch ([PATCH v2 1/5] usb: musb: core: Convert babble recover work to delayed work) does not apply to v3.15-rc4 tag. the current musb_core.c does not have the recovery work for musb. Please let me know what I missed. Oops I missed to mention the same. Please try on git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git master The test is done. The babble always causes STUCK_J is reset, MUSB_BABBLE_CTL is 0x44 or 0x4. MUSB reset happens. Thankyou Bin for the help. Can I get a Tested-by from you? Do you think when re-start happens the driver should print a message on console saying re-start due to babble? It would help debug the babble problems while the dynamic debug is off. It prints out a message saying babble condition occured. More over, it re-enumerates all the devices connected as part of Musb re-start. Don't you think that is sufficient enough ? Thanks, -Bin. Thanks, -Bin. I read these linux-usb emails in Gmail, and am not aware of any easy way to extract patches from Gmail. BTY, I tested with TI 3.12.10 kernel, in which I guess the babble handling is similar to this patch set. With TI3.12.10, MISC is always 0x64, so MUSB never restarts. Thanks, -Bin. But the interesting thing is that with TI 3.2 kernel, shorting DP or DM to VBUS causes MISC register to be 0x4, but the result is completely opposite in TI 3.12.10 kernel, which cause MISC to be 0x64. So in the 3.2 kernel, the babble handing resets the controller, but the 3.12.10 does not. Regards, -Bin. my setup , I have a HUB with 4 devices connected , which gives me a Babble interrupt on both connects and disconnects ( Not always though). Anyway, the full glue layer solves this rare condition quite well for me. Is there any downside of this? Daniel -- -George -- To unsubscribe from this lis
[PATCH v2 0/6] Cleanup and fixes for dwc3-omap
The series does some refactoring on dwc3_probe() Patch 1 - Now that we use driver compatible for revision check, remove the unnecessary logic. Patch 2-4 - reduce the size of dwc3_probe() Patch 5 - Fix the crash on dwc3_omap removal Patch 6 - Addresses the issue of xhci hang while resuming from system sleep. George Cherian (6): usb: dwc3: dwc3-omap: Remove x_major calculation from revision register usb: dwc3: dwc3-omap: Add dwc3_omap_map_offset() function usb: dwc3: dwc3-omap: Add dwc3_omap_set_utmi_mode() function usb: dwc3: dwc3-omap: Add dwc3_omap_extcon_register function usb: dwc3: dwc3-omap: Fix the crash on module removal usb: dwc3: dwc3-omap: Disable/Enable only wrapper interrupts in prepare/complete drivers/usb/dwc3/dwc3-omap.c | 186 ++- 1 file changed, 97 insertions(+), 89 deletions(-) -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 2/6] usb: dwc3: dwc3-omap: Add dwc3_omap_map_offset() function
Move map offset to its own seperate function. Improve code readability, decrease the dwc3_probe() size. Signed-off-by: George Cherian --- drivers/usb/dwc3/dwc3-omap.c | 31 +++ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 53f6490..0df8adf 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -378,6 +378,24 @@ static int dwc3_omap_vbus_notifier(struct notifier_block *nb, return NOTIFY_DONE; } +static void dwc3_omap_map_offset(struct dwc3_omap *omap) +{ + struct device_node *node = omap->dev->of_node; + + /* Differentiate between OMAP5 and AM437x +* For OMAP5(ES2.0) and AM437x x_major is 2 even though there are +* changes in wrapper registers, Using dt compatible for AM437x +*/ + + if (of_device_is_compatible(node, "ti,am437x-dwc3")) { + omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET; + omap->irq0_offset = USBOTGSS_IRQ0_OFFSET; + omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET; + omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET; + omap->debug_offset = USBOTGSS_DEBUG_OFFSET; + } +} + static int dwc3_omap_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -442,18 +460,7 @@ static int dwc3_omap_probe(struct platform_device *pdev) goto err0; } - /* Differentiate between OMAP5 and AM437x -* For OMAP5(ES2.0) and AM437x x_major is 2 even though there are -* changes in wrapper registers, Using dt compatible for AM437x -*/ - - if (of_device_is_compatible(node, "ti,am437x-dwc3")) { - omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET; - omap->irq0_offset = USBOTGSS_IRQ0_OFFSET; - omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET; - omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET; - omap->debug_offset = USBOTGSS_DEBUG_OFFSET; - } + dwc3_omap_map_offset(omap); reg = dwc3_omap_read_utmi_status(omap); -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 3/6] usb: dwc3: dwc3-omap: Add dwc3_omap_set_utmi_mode() function
Move find and set the utmi mode to its own seperate function. Improve code readability, decrease the dwc3_probe() size. Signed-off-by: George Cherian --- drivers/usb/dwc3/dwc3-omap.c | 44 +--- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 0df8adf..2223ab8 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -396,6 +396,30 @@ static void dwc3_omap_map_offset(struct dwc3_omap *omap) } } +static void dwc3_omap_set_utmi_mode(struct dwc3_omap *omap) +{ + u32 reg; + struct device_node *node = omap->dev->of_node; + int utmi_mode = 0; + + reg = dwc3_omap_read_utmi_status(omap); + + of_property_read_u32(node, "utmi-mode", &utmi_mode); + + switch (utmi_mode) { + case DWC3_OMAP_UTMI_MODE_SW: + reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE; + break; + case DWC3_OMAP_UTMI_MODE_HW: + reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE; + break; + default: + dev_dbg(omap->dev, "UNKNOWN utmi mode %d\n", utmi_mode); + } + + dwc3_omap_write_utmi_status(omap, reg); +} + static int dwc3_omap_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -409,8 +433,6 @@ static int dwc3_omap_probe(struct platform_device *pdev) int ret = -ENOMEM; int irq; - int utmi_mode = 0; - u32 reg; void __iomem*base; @@ -461,23 +483,7 @@ static int dwc3_omap_probe(struct platform_device *pdev) } dwc3_omap_map_offset(omap); - - reg = dwc3_omap_read_utmi_status(omap); - - of_property_read_u32(node, "utmi-mode", &utmi_mode); - - switch (utmi_mode) { - case DWC3_OMAP_UTMI_MODE_SW: - reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE; - break; - case DWC3_OMAP_UTMI_MODE_HW: - reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE; - break; - default: - dev_dbg(dev, "UNKNOWN utmi mode %d\n", utmi_mode); - } - - dwc3_omap_write_utmi_status(omap, reg); + dwc3_omap_set_utmi_mode(omap); /* check the DMA Status */ reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG); -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 1/6] usb: dwc3: dwc3-omap: Remove x_major calculation from revision register
Remove the x_major calculation logic from the wrapper revision register to differentiate between OMAP5 and AM437x. This was done to find the register offsets of wrapper register. Now that We do it using dt compatible, remove the whole logic. Signed-off-by: George Cherian --- drivers/usb/dwc3/dwc3-omap.c | 35 +++ 1 file changed, 3 insertions(+), 32 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 1160ff4..53f6490 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -77,10 +77,6 @@ #define USBOTGSS_DEV_EBC_EN0x0110 #define USBOTGSS_DEBUG_OFFSET 0x0600 -/* REVISION REGISTER */ -#define USBOTGSS_REVISION_XMAJOR(reg) ((reg >> 8) & 0x7) -#define USBOTGSS_REVISION_XMAJOR1 1 -#define USBOTGSS_REVISION_XMAJOR2 2 /* SYSCONFIG REGISTER */ #define USBOTGSS_SYSCONFIG_DMADISABLE (1 << 16) @@ -129,7 +125,6 @@ struct dwc3_omap { u32 irq_eoi_offset; u32 debug_offset; u32 irq0_offset; - u32 revision; u32 dma_status:1; @@ -397,7 +392,6 @@ static int dwc3_omap_probe(struct platform_device *pdev) int irq; int utmi_mode = 0; - int x_major; u32 reg; @@ -448,32 +442,9 @@ static int dwc3_omap_probe(struct platform_device *pdev) goto err0; } - reg = dwc3_omap_readl(omap->base, USBOTGSS_REVISION); - omap->revision = reg; - x_major = USBOTGSS_REVISION_XMAJOR(reg); - - /* Differentiate between OMAP5 and AM437x */ - switch (x_major) { - case USBOTGSS_REVISION_XMAJOR1: - case USBOTGSS_REVISION_XMAJOR2: - omap->irq_eoi_offset = 0; - omap->irq0_offset = 0; - omap->irqmisc_offset = 0; - omap->utmi_otg_offset = 0; - omap->debug_offset = 0; - break; - default: - /* Default to the latest revision */ - omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET; - omap->irq0_offset = USBOTGSS_IRQ0_OFFSET; - omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET; - omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET; - omap->debug_offset = USBOTGSS_DEBUG_OFFSET; - break; - } - - /* For OMAP5(ES2.0) and AM437x x_major is 2 even though there are -* changes in wrapper registers, Using dt compatible for aegis + /* Differentiate between OMAP5 and AM437x +* For OMAP5(ES2.0) and AM437x x_major is 2 even though there are +* changes in wrapper registers, Using dt compatible for AM437x */ if (of_device_is_compatible(node, "ti,am437x-dwc3")) { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 5/6] usb: dwc3: dwc3-omap: Fix the crash on module removal
Following crash is seen on dwc3_omap removal Unable to handle kernel NULL pointer dereference at virtual address 0018 pgd = ec098000 [0018] *pgd=ad1f9831, *pte=, *ppte= Internal error: Oops: 17 [#1] SMP ARM Modules linked in: usb_f_ss_lb g_zero usb_f_acm u_serial usb_f_ecm u_ether libcomposite configfs snd_usb_audio snd_usbmidi_lib snd_rawmidi snd_hwdep snd_soc_omap snd_pcm_dmaengine snd_soc_core snd_compress snd_pcm snd_tim] CPU: 0 PID: 1296 Comm: rmmod Tainted: GW 3.15.0-rc4-02716-g95c4e18-dirty #10 task: ed05a080 ti: ec368000 task.ti: ec368000 PC is at release_resource+0x14/0x7c LR is at release_resource+0x10/0x7c pc : []lr : []psr: 6013 sp : ec369ec0 ip : 6013 fp : 00021008 r10: r9 : ec368000 r8 : c000e7a4 r7 : 0081 r6 : bf0062c0 r5 : ed7cd000 r4 : ed7d85c0 r3 : r2 : r1 : 0011 r0 : c086d08c Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user Control: 10c5387d Table: ac098059 DAC: 0015 Process rmmod (pid: 1296, stack limit = 0xec368248) Stack: (0xec369ec0 to 0xec36a000) 9ec0: 0001 ed7cd000 c034de94 ed7cd010 ed7cd000 c034e194 9ee0: bf0062cc ed7cd010 c03490b0 ed154cc0 ed4c2570 ed2b8410 ed156810 ed156810 bf006d24 c034db9c c034db84 c034c518 9f20: bf006d24 ed156810 bf006d24 c034cd2c bf006d24 bf006d68 0800 c034c340 9f40: c00a9e5c 0020 bf006d68 0800 ec369f4c 33637764 9f60: 616d6f5f 0070 0001 ec368000 ed05a080 c000e670 0001 c0084010 9f80: 00021088 0800 00021088 0081 8010 e6f4 00021088 0800 9fa0: 00021088 c000e5e0 00021088 0800 000210b8 0800 e04f6d00 e04f6d00 9fc0: 00021088 0800 00021088 0081 0001 be91de08 00021008 9fe0: 4d768880 be91dbb4 b6fc5984 4d76888c 8010 000210b8 [] (release_resource) from [] (platform_device_del+0x6c/0x9c) [] (platform_device_del) from [] (platform_device_unregister+0xc/0x18) [] (platform_device_unregister) from [] (dwc3_omap_remove_core+0xc/0x14 [dwc3_omap]) [] (dwc3_omap_remove_core [dwc3_omap]) from [] (device_for_each_child+0x34/0x74) [] (device_for_each_child) from [] (dwc3_omap_remove+0x6c/0x78 [dwc3_omap]) [] (dwc3_omap_remove [dwc3_omap]) from [] (platform_drv_remove+0x18/0x1c) [] (platform_drv_remove) from [] (__device_release_driver+0x70/0xc8) [] (__device_release_driver) from [] (driver_detach+0xb4/0xb8) [] (driver_detach) from [] (bus_remove_driver+0x4c/0x90) [] (bus_remove_driver) from [] (SyS_delete_module+0x10c/0x198) [] (SyS_delete_module) from [] (ret_fast_syscall+0x0/0x48) Code: e1a04000 e59f0068 eb14505e e5943010 (e5932018) ---[ end trace 7e2a8746ff4fc811 ]--- Segmentation fault Signed-off-by: George Cherian --- drivers/usb/dwc3/dwc3-omap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 131d75a..e4f681a 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -317,7 +317,7 @@ static int dwc3_omap_remove_core(struct device *dev, void *c) { struct platform_device *pdev = to_platform_device(dev); - platform_device_unregister(pdev); + of_device_unregister(pdev); return 0; } -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 4/6] usb: dwc3: dwc3-omap: Add dwc3_omap_extcon_register function
Move the extcon related code to its own function. Improve code readability, decrease the dwc3_probe() size. Signed-off-by: George Cherian --- drivers/usb/dwc3/dwc3-omap.c | 65 ++-- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 2223ab8..131d75a 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -420,6 +420,42 @@ static void dwc3_omap_set_utmi_mode(struct dwc3_omap *omap) dwc3_omap_write_utmi_status(omap, reg); } +static int dwc3_omap_extcon_register(struct dwc3_omap *omap) +{ + u32 ret; + struct device_node *node = omap->dev->of_node; + struct extcon_dev *edev; + + if (of_property_read_bool(node, "extcon")) { + edev = extcon_get_edev_by_phandle(omap->dev, 0); + if (IS_ERR(edev)) { + dev_vdbg(omap->dev, "couldn't get extcon device\n"); + return -EPROBE_DEFER; + } + + omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier; + ret = extcon_register_interest(&omap->extcon_vbus_dev, + edev->name, "USB", + &omap->vbus_nb); + if (ret < 0) + dev_vdbg(omap->dev, "failed to register notifier for USB\n"); + + omap->id_nb.notifier_call = dwc3_omap_id_notifier; + ret = extcon_register_interest(&omap->extcon_id_dev, + edev->name, "USB-HOST", + &omap->id_nb); + if (ret < 0) + dev_vdbg(omap->dev, "failed to register notifier for USB-HOST\n"); + + if (extcon_get_cable_state(edev, "USB") == true) + dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID); + if (extcon_get_cable_state(edev, "USB-HOST") == true) + dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND); + } + + return 0; +} + static int dwc3_omap_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -427,7 +463,6 @@ static int dwc3_omap_probe(struct platform_device *pdev) struct dwc3_omap*omap; struct resource *res; struct device *dev = &pdev->dev; - struct extcon_dev *edev; struct regulator*vbus_reg = NULL; int ret = -ENOMEM; @@ -499,31 +534,9 @@ static int dwc3_omap_probe(struct platform_device *pdev) dwc3_omap_enable_irqs(omap); - if (of_property_read_bool(node, "extcon")) { - edev = extcon_get_edev_by_phandle(dev, 0); - if (IS_ERR(edev)) { - dev_vdbg(dev, "couldn't get extcon device\n"); - ret = -EPROBE_DEFER; - goto err2; - } - - omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier; - ret = extcon_register_interest(&omap->extcon_vbus_dev, - edev->name, "USB", &omap->vbus_nb); - if (ret < 0) - dev_vdbg(dev, "failed to register notifier for USB\n"); - omap->id_nb.notifier_call = dwc3_omap_id_notifier; - ret = extcon_register_interest(&omap->extcon_id_dev, edev->name, -"USB-HOST", &omap->id_nb); - if (ret < 0) - dev_vdbg(dev, - "failed to register notifier for USB-HOST\n"); - - if (extcon_get_cable_state(edev, "USB") == true) - dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID); - if (extcon_get_cable_state(edev, "USB-HOST") == true) - dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND); - } + ret = dwc3_omap_extcon_register(omap); + if (ret < 0) + goto err2; ret = of_platform_populate(node, NULL, NULL, dev); if (ret) { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 6/6] usb: dwc3: dwc3-omap: Disable/Enable only wrapper interrupts in prepare/complete
The dwc3 wrapper driver should not be fiddling with the core interrupts. Disabling the core interrupts in prepare stops xhci from proper operation. So remove disable/enable of core interrupts from prepare/complete. Signed-off-by: George Cherian --- drivers/usb/dwc3/dwc3-omap.c | 15 +-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index e4f681a..3f86f29 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -596,7 +596,7 @@ static int dwc3_omap_prepare(struct device *dev) { struct dwc3_omap*omap = dev_get_drvdata(dev); - dwc3_omap_disable_irqs(omap); + dwc3_omap_write_irqmisc_set(omap, 0x00); return 0; } @@ -604,8 +604,19 @@ static int dwc3_omap_prepare(struct device *dev) static void dwc3_omap_complete(struct device *dev) { struct dwc3_omap*omap = dev_get_drvdata(dev); + u32 reg; - dwc3_omap_enable_irqs(omap); + reg = (USBOTGSS_IRQMISC_OEVT | + USBOTGSS_IRQMISC_DRVVBUS_RISE | + USBOTGSS_IRQMISC_CHRGVBUS_RISE | + USBOTGSS_IRQMISC_DISCHRGVBUS_RISE | + USBOTGSS_IRQMISC_IDPULLUP_RISE | + USBOTGSS_IRQMISC_DRVVBUS_FALL | + USBOTGSS_IRQMISC_CHRGVBUS_FALL | + USBOTGSS_IRQMISC_DISCHRGVBUS_FALL | + USBOTGSS_IRQMISC_IDPULLUP_FALL); + + dwc3_omap_write_irqmisc_set(omap, reg); } static int dwc3_omap_suspend(struct device *dev) -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 0/5] Add support for SW babble Control
Hi Bin, On 5/14/2014 10:13 PM, Bin Liu wrote: George, On Wed, May 14, 2014 at 9:34 AM, Bin Liu wrote: George, On Wed, May 14, 2014 at 12:37 AM, George Cherian wrote: On 5/14/2014 12:07 AM, Bin Liu wrote: Hi, On Tue, May 13, 2014 at 8:24 AM, George Cherian wrote: Hi Daniel, On 5/13/2014 6:44 PM, Daniel Mack wrote: Hi George, On 05/13/2014 02:57 PM, George Cherian wrote: I never enabled the MUSB_BABBLE_SW_SESSION_CTRL in the MUSB_BABBLE_CTL reg. can you try with the following patch. diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 1ae6681..1160cd1 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -477,8 +477,11 @@ static int dsps_musb_init(struct musb *musb) * logic enabled. */ val = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); - if (val == MUSB_BABBLE_RCV_DISABLE) + if (val == MUSB_BABBLE_RCV_DISABLE) { glue->sw_babble_enabled = true; + val |= MUSB_BABBLE_SW_SESSION_CTRL; + dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, val); + } ret = dsps_musb_dbg_init(musb, glue); if (ret) MUSB_BABBLE_STUCK_J still remains unset, so I get the same result as without the patch: a full glue reset is conducted. Do I get you right that you expect MUSB_BABBLE_STUCK_J to be set in babble conditions when MUSB_BABBLE_SW_SESSION_CTRL is set? Basically, there are 2 types of babble conditions. 1) Transient babble condition - which could be recovered from without an IP reset . 2) Babble condition - which could be recovered from only by doing an IP reset. Looks like you are always hitting case 2 (Most times am also hitting the same). Case 1 is really hard to reproduce. I don't have a reliable method as of now to reproduce this case consistently. [ 19.672373] CAUTION: musb: Babble Interrupt Occurred [ 19.66] musb_stage0_irq 789: unhandled DISCONNECT transition (a_wait_bcon) [ 19.685815] usb 1-1: USB disconnect, device number 3 [ 19.769720] musb-hdrc musb-hdrc.0.auto: babble: MUSB_BABBLE_CTL value 44 [ 19.776765] musb-hdrc musb-hdrc.0.auto: STUCK_J is reset I don't quite follow, especially as I lack documentation of the IP core. How do you test babble errors, is there any way to force them to happen reliably? There is no 100% reliable method to force it to happen. Following is I have a way to force babble happen reliably - shorting DP or DM to VBUS. I opened the far-end plug of the USB cable, so I can easily short DP or DM to VBUS. Good to know that you have a reliable way to test babble condition. Can you please do a quick test on 3.15.0-rc4 with the series applied? In case of any assistance please do let me know. Sure, but could you please re-send those patches to my corporate email so that I can apply them from Thunderbird? You don't have to resend the patches. Nishanth Menon showed me a way to extract the patch from Gmail - Thanks Nishanth. But which repo do you want to me test with? The first patch ([PATCH v2 1/5] usb: musb: core: Convert babble recover work to delayed work) does not apply to v3.15-rc4 tag. the current musb_core.c does not have the recovery work for musb. Please let me know what I missed. Oops I missed to mention the same. Please try on git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git master Thanks, -Bin. I read these linux-usb emails in Gmail, and am not aware of any easy way to extract patches from Gmail. BTY, I tested with TI 3.12.10 kernel, in which I guess the babble handling is similar to this patch set. With TI3.12.10, MISC is always 0x64, so MUSB never restarts. Thanks, -Bin. But the interesting thing is that with TI 3.2 kernel, shorting DP or DM to VBUS causes MISC register to be 0x4, but the result is completely opposite in TI 3.12.10 kernel, which cause MISC to be 0x64. So in the 3.2 kernel, the babble handing resets the controller, but the 3.12.10 does not. Regards, -Bin. my setup , I have a HUB with 4 devices connected , which gives me a Babble interrupt on both connects and disconnects ( Not always though). Anyway, the full glue layer solves this rare condition quite well for me. Is there any downside of this? Daniel -- -George -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- -George -- -George -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH] ARM: dts: am33xx: Re-arrange the USB dt to reflect the h/w configuration
Hi Tony, On 5/15/2014 3:20 AM, Tony Lindgren wrote: * George Cherian [140508 23:34]: Re arrange the USB dt for AM33xx to take it a bit closer to the hardware configuration. The USBSS is designed as follows USB control Module 0x44e10_0620 USBSS 0x4740_ USB00x4740_1000 USB0_PHY0x4740_1300 USB0_CORE 0x4740_1400 USB10x4740_1800 USB1_PHY0x4740_1b00 USB1_CORE 0x4740_1c00 CPPI DMA Controller 0x4740_2000 CPPI DMA Scheduler 0x4740_3000 Queue Manager 0x4740_4000 So model the DT as follows USBSS { usb_ctrl_mod: { 0x44e10_0620 } usb0: { 0x4740_1000 0x4740_1400 } usb0_phy:{ 0x4740_1300 } usb1:{ 0x4740_1800 0x4740_1c00 } usb1_phy: { 0x4740_1b00 } cppi41dma: { 0x4740_2000 0x4740_3000 0x4740_4000 } } Is this just a cosmetic change or is this trying to workaround some edma related init order issue? Please ignore this patch. Was trying to workaround some dma and phy related issues. The same got fixed with following http://www.spinics.net/lists/linux-usb/msg107244.html Regards, Tony -- -George -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 5/5] usb: dwc3: dwc3-omap: Disable/Enable core interrupts in Suspend/Resume
On 5/13/2014 9:20 PM, Felipe Balbi wrote: Hi, On Thu, May 08, 2014 at 03:03:07PM +0530, George Cherian wrote: Enabling the core interrupts in complete is too late for XHCI, and stops xhci from proper operation. So remove prepare and complete and disable/enable isn't this a bug in xhci ? I mean the driver should make no assumption as to when IRQs are enabled, why do we need to enable IRQs earlier when the device is only considered "ready for use" after ->complete() finishes executing ? I dont think its a bug in xhci. In case of xhci-pci driver it actually does an hcd->driver->pci_suspend (xhci_suspend) followed by synchronize_irq() and the does a pci_disable_device(). In resume path it calls pci_enable_device() followed by hcd->driver->pci_resume(xhci_resume). In case of dwc3-omap we do have a wrapper register which can still disable the XHCI IRQs even though the xhci driver enables the interrupts internally. Now dwc3-omap wrapper driver should not actually fiddle with the core Interrupt enable/disable except in probe/remove. From documentation we have: 107 * @complete: Undo the changes made by @prepare(). This method is executed for 108 * all kinds of resume transitions, following one of the resume callbacks: 109 * @resume(), @thaw(), @restore(). Also called if the state transition 110 * fails before the driver's suspend callback: @suspend(), @freeze() or 111 * @poweroff(), can be executed (e.g. if the suspend callback fails for one 112 * of the other devices that the PM core has unsuccessfully attempted to 113 * suspend earlier). 114 * The PM core executes subsystem-level @complete() after it has executed 115 * the appropriate resume callbacks for all devices. which tells me that using ->complete() to reenable IRQs is ok here. Specially when you consider that the role of ->prepare() is to prevent new children from being created and, for a USB host, that means we should prevent hub port changes. Probably the patch should have been to still keep the complete/prepare in place but not disable the core interrupts, rather enable/disable only the wrapper interrupt. cheers -- -George -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/5] usb: dwc3: dwc3-omap: Add dwc3_omap_map_offset function
On 5/13/2014 9:32 PM, Felipe Balbi wrote: Hi, On Thu, May 08, 2014 at 03:03:03PM +0530, George Cherian wrote: Calculate the wrapper register offsets in a seperate function. Improve code readability, decrease the dwc3_probe() size. Signed-off-by: George Cherian --- drivers/usb/dwc3/dwc3-omap.c | 80 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 1160ff4..872f065 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -383,6 +383,49 @@ static int dwc3_omap_vbus_notifier(struct notifier_block *nb, return NOTIFY_DONE; } +static void dwc3_omap_map_offset(struct dwc3_omap *omap) +{ + u32 reg; + struct device_node *node = omap->dev->of_node; + int x_major; + + reg = dwc3_omap_readl(omap->base, USBOTGSS_REVISION); + omap->revision = reg; + x_major = USBOTGSS_REVISION_XMAJOR(reg); + + /* Differentiate between OMAP5 and AM437x */ + switch (x_major) { + case USBOTGSS_REVISION_XMAJOR1: + case USBOTGSS_REVISION_XMAJOR2: + omap->irq_eoi_offset = 0; + omap->irq0_offset = 0; + omap->irqmisc_offset = 0; + omap->utmi_otg_offset = 0; + omap->debug_offset = 0; + break; + default: + /* Default to the latest revision */ + omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET; + omap->irq0_offset = USBOTGSS_IRQ0_OFFSET; + omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET; + omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET; + omap->debug_offset = USBOTGSS_DEBUG_OFFSET; + break; + } + + /* For OMAP5(ES2.0) and AM437x x_major is 2 even though there are +* changes in wrapper registers, Using dt compatible for aegis +*/ + + if (of_device_is_compatible(node, "ti,am437x-dwc3")) { + omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET; + omap->irq0_offset = USBOTGSS_IRQ0_OFFSET; + omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET; + omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET; + omap->debug_offset = USBOTGSS_DEBUG_OFFSET; + } can you add a patch before $subject which gets rid of the switch statement above since it's pretty much useless now that we use compatible strings to differentiate omap5 and am437x ?' okay will do in v2. -- -George -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 0/5] Add support for SW babble Control
On 5/14/2014 12:07 AM, Bin Liu wrote: Hi, On Tue, May 13, 2014 at 8:24 AM, George Cherian wrote: Hi Daniel, On 5/13/2014 6:44 PM, Daniel Mack wrote: Hi George, On 05/13/2014 02:57 PM, George Cherian wrote: I never enabled the MUSB_BABBLE_SW_SESSION_CTRL in the MUSB_BABBLE_CTL reg. can you try with the following patch. diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 1ae6681..1160cd1 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -477,8 +477,11 @@ static int dsps_musb_init(struct musb *musb) * logic enabled. */ val = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); - if (val == MUSB_BABBLE_RCV_DISABLE) + if (val == MUSB_BABBLE_RCV_DISABLE) { glue->sw_babble_enabled = true; + val |= MUSB_BABBLE_SW_SESSION_CTRL; + dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, val); + } ret = dsps_musb_dbg_init(musb, glue); if (ret) MUSB_BABBLE_STUCK_J still remains unset, so I get the same result as without the patch: a full glue reset is conducted. Do I get you right that you expect MUSB_BABBLE_STUCK_J to be set in babble conditions when MUSB_BABBLE_SW_SESSION_CTRL is set? Basically, there are 2 types of babble conditions. 1) Transient babble condition - which could be recovered from without an IP reset . 2) Babble condition - which could be recovered from only by doing an IP reset. Looks like you are always hitting case 2 (Most times am also hitting the same). Case 1 is really hard to reproduce. I don't have a reliable method as of now to reproduce this case consistently. [ 19.672373] CAUTION: musb: Babble Interrupt Occurred [ 19.66] musb_stage0_irq 789: unhandled DISCONNECT transition (a_wait_bcon) [ 19.685815] usb 1-1: USB disconnect, device number 3 [ 19.769720] musb-hdrc musb-hdrc.0.auto: babble: MUSB_BABBLE_CTL value 44 [ 19.776765] musb-hdrc musb-hdrc.0.auto: STUCK_J is reset I don't quite follow, especially as I lack documentation of the IP core. How do you test babble errors, is there any way to force them to happen reliably? There is no 100% reliable method to force it to happen. Following is I have a way to force babble happen reliably - shorting DP or DM to VBUS. I opened the far-end plug of the USB cable, so I can easily short DP or DM to VBUS. Good to know that you have a reliable way to test babble condition. Can you please do a quick test on 3.15.0-rc4 with the series applied? In case of any assistance please do let me know. But the interesting thing is that with TI 3.2 kernel, shorting DP or DM to VBUS causes MISC register to be 0x4, but the result is completely opposite in TI 3.12.10 kernel, which cause MISC to be 0x64. So in the 3.2 kernel, the babble handing resets the controller, but the 3.12.10 does not. Regards, -Bin. my setup , I have a HUB with 4 devices connected , which gives me a Babble interrupt on both connects and disconnects ( Not always though). Anyway, the full glue layer solves this rare condition quite well for me. Is there any downside of this? Daniel -- -George -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- -George -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 0/5] Add support for SW babble Control
Hi Daniel, On 5/13/2014 6:44 PM, Daniel Mack wrote: Hi George, On 05/13/2014 02:57 PM, George Cherian wrote: I never enabled the MUSB_BABBLE_SW_SESSION_CTRL in the MUSB_BABBLE_CTL reg. can you try with the following patch. diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 1ae6681..1160cd1 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -477,8 +477,11 @@ static int dsps_musb_init(struct musb *musb) * logic enabled. */ val = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); - if (val == MUSB_BABBLE_RCV_DISABLE) + if (val == MUSB_BABBLE_RCV_DISABLE) { glue->sw_babble_enabled = true; + val |= MUSB_BABBLE_SW_SESSION_CTRL; + dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, val); + } ret = dsps_musb_dbg_init(musb, glue); if (ret) MUSB_BABBLE_STUCK_J still remains unset, so I get the same result as without the patch: a full glue reset is conducted. Do I get you right that you expect MUSB_BABBLE_STUCK_J to be set in babble conditions when MUSB_BABBLE_SW_SESSION_CTRL is set? Basically, there are 2 types of babble conditions. 1) Transient babble condition - which could be recovered from without an IP reset . 2) Babble condition - which could be recovered from only by doing an IP reset. Looks like you are always hitting case 2 (Most times am also hitting the same). Case 1 is really hard to reproduce. I don't have a reliable method as of now to reproduce this case consistently. [ 19.672373] CAUTION: musb: Babble Interrupt Occurred [ 19.66] musb_stage0_irq 789: unhandled DISCONNECT transition (a_wait_bcon) [ 19.685815] usb 1-1: USB disconnect, device number 3 [ 19.769720] musb-hdrc musb-hdrc.0.auto: babble: MUSB_BABBLE_CTL value 44 [ 19.776765] musb-hdrc musb-hdrc.0.auto: STUCK_J is reset I don't quite follow, especially as I lack documentation of the IP core. How do you test babble errors, is there any way to force them to happen reliably? There is no 100% reliable method to force it to happen. Following is my setup , I have a HUB with 4 devices connected , which gives me a Babble interrupt on both connects and disconnects ( Not always though). Anyway, the full glue layer solves this rare condition quite well for me. Is there any downside of this? Daniel -- -George -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 0/5] Add support for SW babble Control
On 5/13/2014 5:50 PM, Daniel Mack wrote: On 05/13/2014 01:57 PM, George Cherian wrote: On 5/13/2014 3:16 PM, Daniel Mack wrote: On 05/13/2014 10:31 AM, George Cherian wrote: Series add support for SW babble control logic found in new silicon versions of AM335x. Runtime differentiation of silicon version is done by checking the BABBLE_CTL register. For newer silicon the register default value read is 0x4 and for older versions its 0x0. I tested this on a AM33xx platform and don't see any regression at least. This hardware has MUSB_BABBLE_CTL == MUSB_BABBLE_RCV_DISABLE. Anything particular you want me to test as well? Are you seeing a wrapper restart done always or does it continue with a restart after the babble condition? MUSB_BABBLE_CTL == MUSB_BABBLE_RCV_DISABLE, so sw_babble_control() is called from dsps_musb_reset(). However, MUSB_BABBLE_CTL still returns 0x04 (MUSB_BABBLE_RCV_DISABLE) inside that function, which means (babble_ctl & MUSB_BABBLE_STUCK_J) is false, and hence sw_babble_control() returns 1. Ah Missed a critical portion My bad... I never enabled the MUSB_BABBLE_SW_SESSION_CTRL in the MUSB_BABBLE_CTL reg. can you try with the following patch. diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 1ae6681..1160cd1 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -477,8 +477,11 @@ static int dsps_musb_init(struct musb *musb) * logic enabled. */ val = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); - if (val == MUSB_BABBLE_RCV_DISABLE) + if (val == MUSB_BABBLE_RCV_DISABLE) { glue->sw_babble_enabled = true; + val |= MUSB_BABBLE_SW_SESSION_CTRL; + dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, val); + } ret = dsps_musb_dbg_init(musb, glue); if (ret) -- 1.8.3.1 I will resend the series, if this works fine. Thanks for all your help. Consequently, the glue is fully reset in this case. Does this help? FWIW, this is the output of dsps_musb_reset() with dev_dbg() enabled: [ 54.066124] CAUTION: musb: Babble Interrupt Occurred [ 54.071856] usb 1-1: USB disconnect, device number 8 [ 54.159495] musb-hdrc musb-hdrc.0.auto: babble: MUSB_BABBLE_CTL value 4 [ 54.166446] musb-hdrc musb-hdrc.0.auto: STUCK_J is reset I only have one exact USB device to reproduce the babble condition, so I guess this is all I can do for now. Same with me also . I also have only one device with which i get the issue. Thanks, Daniel -- -George -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 0/5] Add support for SW babble Control
On 5/13/2014 3:16 PM, Daniel Mack wrote: Hi George, On 05/13/2014 10:31 AM, George Cherian wrote: Series add support for SW babble control logic found in new silicon versions of AM335x. Runtime differentiation of silicon version is done by checking the BABBLE_CTL register. For newer silicon the register default value read is 0x4 and for older versions its 0x0. I tested this on a AM33xx platform and don't see any regression at least. This hardware has MUSB_BABBLE_CTL == MUSB_BABBLE_RCV_DISABLE. Anything particular you want me to test as well? Are you seeing a wrapper restart done always or does it continue with a restart after the babble condition? You can check for "musb_hdrc: setup fifo_mode 4" prints . Thanks, Daniel -- -George -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 1/5] usb: musb: core: Convert babble recover work to delayed work
During babble condition both first disconnect of devices are initiated. Make sure MUSB controller is reset and re-initialized after all disconnects. To acheive this schedule a delayed work for babble rrecovery. While at that convert udelay to usleep_range. Refer Documentation/timers/timers-howto.txt Signed-off-by: George Cherian --- drivers/usb/musb/musb_core.c | 15 --- drivers/usb/musb/musb_core.h | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 61da471..dcadc62 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -850,7 +850,8 @@ b_host: /* handle babble condition */ if (int_usb & MUSB_INTR_BABBLE) - schedule_work(&musb->recover_work); + schedule_delayed_work(&musb->recover_work, + msecs_to_jiffies(100)); #if 0 /* REVISIT ... this would be for multiplexing periodic endpoints, or @@ -1753,16 +1754,16 @@ static void musb_irq_work(struct work_struct *data) /* Recover from babble interrupt conditions */ static void musb_recover_work(struct work_struct *data) { - struct musb *musb = container_of(data, struct musb, recover_work); + struct musb *musb = container_of(data, struct musb, recover_work.work); int status; musb_platform_reset(musb); usb_phy_vbus_off(musb->xceiv); - udelay(100); + usleep_range(100, 200); usb_phy_vbus_on(musb->xceiv); - udelay(100); + usleep_range(100, 200); /* * When a babble condition occurs, the musb controller removes the @@ -1945,7 +1946,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) /* Init IRQ workqueue before request_irq */ INIT_WORK(&musb->irq_work, musb_irq_work); - INIT_WORK(&musb->recover_work, musb_recover_work); + INIT_DELAYED_WORK(&musb->recover_work, musb_recover_work); INIT_DELAYED_WORK(&musb->deassert_reset_work, musb_deassert_reset); INIT_DELAYED_WORK(&musb->finish_resume_work, musb_host_finish_resume); @@ -2041,7 +2042,7 @@ fail4: fail3: cancel_work_sync(&musb->irq_work); - cancel_work_sync(&musb->recover_work); + cancel_delayed_work_sync(&musb->recover_work); cancel_delayed_work_sync(&musb->finish_resume_work); cancel_delayed_work_sync(&musb->deassert_reset_work); if (musb->dma_controller) @@ -2107,7 +2108,7 @@ static int musb_remove(struct platform_device *pdev) dma_controller_destroy(musb->dma_controller); cancel_work_sync(&musb->irq_work); - cancel_work_sync(&musb->recover_work); + cancel_delayed_work_sync(&musb->recover_work); cancel_delayed_work_sync(&musb->finish_resume_work); cancel_delayed_work_sync(&musb->deassert_reset_work); musb_free(musb); diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 47e8874..423cd00 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -297,7 +297,7 @@ struct musb { irqreturn_t (*isr)(int, void *); struct work_struct irq_work; - struct work_struct recover_work; + struct delayed_work recover_work; struct delayed_work deassert_reset_work; struct delayed_work finish_resume_work; u16 hwvers; -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 3/5] usb: musb: core: Convert the musb_platform_reset to have a return value.
Currently musb_platform_reset() is only used by dsps. In case of BABBLE interrupt for other platforms the musb_platform_reset() is a NOP. In such situations no need to re-initialize the endpoints. Also in the latest silicon revision of AM335x, we do have a babble recovery mechanism without resetting the IP block. In preperation to add that support its better to have a rest_done return for musb_platform_reset(). Signed-off-by: George Cherian --- drivers/usb/musb/musb_core.c | 38 +- drivers/usb/musb/musb_core.h | 10 ++ drivers/usb/musb/musb_dsps.c | 3 ++- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index dcadc62..1f8b175 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1755,28 +1755,32 @@ static void musb_irq_work(struct work_struct *data) static void musb_recover_work(struct work_struct *data) { struct musb *musb = container_of(data, struct musb, recover_work.work); - int status; + int status, ret; - musb_platform_reset(musb); + ret = musb_platform_reset(musb); + if (ret < 0) + return; - usb_phy_vbus_off(musb->xceiv); - usleep_range(100, 200); + if (!ret) { + usb_phy_vbus_off(musb->xceiv); + usleep_range(100, 200); - usb_phy_vbus_on(musb->xceiv); - usleep_range(100, 200); + usb_phy_vbus_on(musb->xceiv); + usleep_range(100, 200); - /* -* When a babble condition occurs, the musb controller removes the -* session bit and the endpoint config is lost. -*/ - if (musb->dyn_fifo) - status = ep_config_from_table(musb); - else - status = ep_config_from_hw(musb); + /* +* When a babble condition occurs, the musb controller removes the +* session bit and the endpoint config is lost. +*/ + if (musb->dyn_fifo) + status = ep_config_from_table(musb); + else + status = ep_config_from_hw(musb); - /* start the session again */ - if (status == 0) - musb_start(musb); + /* start the session again */ + if (status == 0) + musb_start(musb); + } } /* -- diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 423cd00..3ccb428 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -192,7 +192,7 @@ struct musb_platform_ops { int (*set_mode)(struct musb *musb, u8 mode); void(*try_idle)(struct musb *musb, unsigned long timeout); - void(*reset)(struct musb *musb); + int (*reset)(struct musb *musb); int (*vbus_status)(struct musb *musb); void(*set_vbus)(struct musb *musb, int on); @@ -554,10 +554,12 @@ static inline void musb_platform_try_idle(struct musb *musb, musb->ops->try_idle(musb, timeout); } -static inline void musb_platform_reset(struct musb *musb) +static inline int musb_platform_reset(struct musb *musb) { - if (musb->ops->reset) - musb->ops->reset(musb); + if (!musb->ops->reset) + return -EINVAL; + + return musb->ops->reset(musb); } static inline int musb_platform_get_vbus_status(struct musb *musb) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 74c4193..f6f3087 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -536,7 +536,7 @@ static int dsps_musb_set_mode(struct musb *musb, u8 mode) return 0; } -static void dsps_musb_reset(struct musb *musb) +static int dsps_musb_reset(struct musb *musb) { struct device *dev = musb->controller; struct dsps_glue *glue = dev_get_drvdata(dev->parent); @@ -548,6 +548,7 @@ static void dsps_musb_reset(struct musb *musb) usleep_range(100, 200); usb_phy_init(musb->xceiv); + return 0; } static struct musb_platform_ops dsps_ops = { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 0/5] Add support for SW babble Control
Series add support for SW babble control logic found in new silicon versions of AM335x. Runtime differentiation of silicon version is done by checking the BABBLE_CTL register. For newer silicon the register default value read is 0x4 and for older versions its 0x0. Patch 1 -> Convert recover work to delayed work. Patch 2 -> usb_phy_vbus_(off/_on) are NOPs for am335x PHY so use usb_phy(_shutdown/_init) in musb_platform_reset() Patch 3 -> Add return value for musb_platform_reset() in prepration to support SW babble_ctrl Patch 4 -> Add the sw_babble_control() Patch 5 -> Enable sw babble control for newer silicon v2 -> v3 : Modify musb_platform_reset() to return zero on success. v1 -> v2 : Fixed the issue with Patch 5. In v1 it was not calling sw_babble_control(). George Cherian (5): usb: musb: core: Convert babble recover work to delayed work usb: musb: dsps: Call usb_phy(_shutdown/_init) during musb_platform_reset() usb: musb: core: Convert the musb_platform_reset to have a return value. usb: musb: dsps: Add the sw_babble_control() usb: musb: dsps: Enable sw babble control for newer silicon drivers/usb/musb/musb_core.c | 49 ++ drivers/usb/musb/musb_core.h | 12 --- drivers/usb/musb/musb_dsps.c | 83 ++-- drivers/usb/musb/musb_regs.h | 7 4 files changed, 121 insertions(+), 30 deletions(-) -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 2/5] usb: musb: dsps: Call usb_phy(_shutdown/_init) during musb_platform_reset()
For DSPS platform usb_phy_vbus(_off/_on) are NOPs. So during musb_platform_reset() call usb_phy(_shutdown/_init) Signed-off-by: George Cherian --- drivers/usb/musb/musb_dsps.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 51beb13..74c4193 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -543,7 +543,11 @@ static void dsps_musb_reset(struct musb *musb) const struct dsps_musb_wrapper *wrp = glue->wrp; dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset)); - udelay(100); + usleep_range(100, 200); + usb_phy_shutdown(musb->xceiv); + usleep_range(100, 200); + usb_phy_init(musb->xceiv); + } static struct musb_platform_ops dsps_ops = { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 5/5] usb: musb: dsps: Enable sw babble control for newer silicon
Find whether we are running on newer silicon. The babble control register reads 0x4 by default in newer silicon as opposed to 0 in old versions of AM335x. Based on this enable the sw babble control logic. Signed-off-by: George Cherian --- drivers/usb/musb/musb_dsps.c | 34 -- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index eb1985a..1ae6681 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -136,6 +136,7 @@ struct dsps_glue { const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */ struct timer_list timer;/* otg_workaround timer */ unsigned long last_timer;/* last timer data for each instance */ + bool sw_babble_enabled; struct dsps_context context; struct debugfs_regset32 regset; @@ -469,6 +470,16 @@ static int dsps_musb_init(struct musb *musb) val &= ~(1 << wrp->otg_disable); dsps_writel(musb->ctrl_base, wrp->phy_utmi, val); + /* +* Check whether the dsps version has babble control enabled. +* In latest silicon revision the babble control logic is enabled. +* If MUSB_BABBLE_CTL returns 0x4 then we have the babble control +* logic enabled. +*/ + val = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); + if (val == MUSB_BABBLE_RCV_DISABLE) + glue->sw_babble_enabled = true; + ret = dsps_musb_dbg_init(musb, glue); if (ret) return ret; @@ -591,14 +602,25 @@ static int dsps_musb_reset(struct musb *musb) struct device *dev = musb->controller; struct dsps_glue *glue = dev_get_drvdata(dev->parent); const struct dsps_musb_wrapper *wrp = glue->wrp; + int session_restart = 0; - dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset)); - usleep_range(100, 200); - usb_phy_shutdown(musb->xceiv); - usleep_range(100, 200); - usb_phy_init(musb->xceiv); + if (glue->sw_babble_enabled) + session_restart = sw_babble_control(musb); + /* +* In case of new silicon version babble condition can be recovered +* without resetting the MUSB. But for older silicon versions, MUSB +* reset is needed +*/ + if (session_restart || !glue->sw_babble_enabled) { + dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset)); + usleep_range(100, 200); + usb_phy_shutdown(musb->xceiv); + usleep_range(100, 200); + usb_phy_init(musb->xceiv); + session_restart = 1; + } - return 0; + return !session_restart; } static struct musb_platform_ops dsps_ops = { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 4/5] usb: musb: dsps: Add the sw_babble_control()
Add sw_babble_control() logic to differentiate between transient babble and real babble condition. Also add the SW babble control register definitions. Babble control register logic is implemented in the latest revision of AM335x. Signed-off-by: George Cherian --- drivers/usb/musb/musb_dsps.c | 50 drivers/usb/musb/musb_regs.h | 7 +++ 2 files changed, 57 insertions(+) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index f6f3087..eb1985a 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -536,6 +536,56 @@ static int dsps_musb_set_mode(struct musb *musb, u8 mode) return 0; } +static int sw_babble_control(struct musb *musb) +{ + int timeout = 10; + u8 babble_ctl, session_restart = 0; + + babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); + dev_dbg(musb->controller, "babble: MUSB_BABBLE_CTL value %x\n", + babble_ctl); + /* +* check line monitor flag to check whether babble is +* due to noise +*/ + dev_dbg(musb->controller, "STUCK_J is %s\n", + babble_ctl & MUSB_BABBLE_STUCK_J ? "set" : "reset"); + + if (babble_ctl & MUSB_BABBLE_STUCK_J) { + /* +* babble is due to noise, then set transmit idle (d7 bit) +* to resume normal operation +*/ + babble_ctl = musb_readb(musb->mregs, MUSB_BABBLE_CTL); + babble_ctl |= MUSB_BABBLE_FORCE_TXIDLE; + dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, babble_ctl); + + /* wait till line monitor flag cleared */ + dev_dbg(musb->controller, "Set TXIDLE, wait J to clear\n"); + do { + babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); + udelay(1); + } while ((babble_ctl & MUSB_BABBLE_STUCK_J) && timeout--); + + /* check whether stuck_at_j bit cleared */ + if (babble_ctl & MUSB_BABBLE_STUCK_J) { + /* +* real babble condition is occured +* restart the controller to start the +* session again +*/ + dev_dbg(musb->controller, "J not cleared, misc (%x)\n", + babble_ctl); + session_restart = 1; + } + + } else { + session_restart = 1; + } + + return session_restart; +} + static int dsps_musb_reset(struct musb *musb) { struct device *dev = musb->controller; diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h index 03f2655..b9bcda5 100644 --- a/drivers/usb/musb/musb_regs.h +++ b/drivers/usb/musb/musb_regs.h @@ -72,6 +72,12 @@ #define MUSB_DEVCTL_HR 0x02 #define MUSB_DEVCTL_SESSION0x01 +/* BABBLE_CTL */ +#define MUSB_BABBLE_FORCE_TXIDLE 0x80 +#define MUSB_BABBLE_SW_SESSION_CTRL0x40 +#define MUSB_BABBLE_STUCK_J0x20 +#define MUSB_BABBLE_RCV_DISABLE0x04 + /* MUSB ULPI VBUSCONTROL */ #define MUSB_ULPI_USE_EXTVBUS 0x01 #define MUSB_ULPI_USE_EXTVBUSIND 0x02 @@ -246,6 +252,7 @@ */ #define MUSB_DEVCTL0x60/* 8 bit */ +#define MUSB_BABBLE_CTL0x61/* 8 bit */ /* These are always controlled through the INDEX register */ #define MUSB_TXFIFOSZ 0x62/* 8-bit (see masks) */ -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] ARM: dts: am33xx: Move the cppi41dma node so it's probed early
On 4/25/2014 2:41 AM, Ezequiel Garcia wrote: The DMA controller is needed for the USB controller to be correctly registered. Therefore, if the DMA node is located at the end an unecessary probe deferral is produced systematically. This is easily fixed by moving the node at the beggining of the child list, so it's probed first. Signed-off-by: Ezequiel Garcia Acked-by: George Cherian -- v1->v2: * Added a comment to prevent a future clean-up based on the memory offset. arch/arm/boot/dts/am33xx.dtsi | 34 -- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi index 9770e35..02e1eb6 100644 --- a/arch/arm/boot/dts/am33xx.dtsi +++ b/arch/arm/boot/dts/am33xx.dtsi @@ -453,6 +453,26 @@ ti,hwmods = "usb_otg_hs"; status = "disabled"; + /* +* The probe order matches the child ordering so the +* dma-controller node must be the first one to prevent +* spurious probe deferrals. +*/ + cppi41dma: dma-controller@47402000 { + compatible = "ti,am3359-cppi41"; + reg = <0x4740 0x1000 + 0x47402000 0x1000 + 0x47403000 0x1000 + 0x47404000 0x4000>; + reg-names = "glue", "controller", "scheduler", "queuemgr"; + interrupts = <17>; + interrupt-names = "glue"; + #dma-cells = <2>; + #dma-channels = <30>; + #dma-requests = <256>; + status = "disabled"; + }; + usb_ctrl_mod: control@44e10620 { compatible = "ti,am335x-usb-ctrl-module"; reg = <0x44e10620 0x10 @@ -556,20 +576,6 @@ "tx14", "tx15"; }; - cppi41dma: dma-controller@47402000 { - compatible = "ti,am3359-cppi41"; - reg = <0x4740 0x1000 - 0x47402000 0x1000 - 0x47403000 0x1000 - 0x47404000 0x4000>; - reg-names = "glue", "controller", "scheduler", "queuemgr"; - interrupts = <17>; - interrupt-names = "glue"; - #dma-cells = <2>; - #dma-channels = <30>; - #dma-requests = <256>; - status = "disabled"; - }; }; epwmss0: epwmss@4830 { -- -George -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC/PATCH] usb: musb: Prevent musb_am335x from being removed
[] (platform_drv_remove+0x18/0x1c) [] (platform_drv_remove) from [] (__device_release_driver+0x70/0xc8) [] (__device_release_driver) from [] (driver_detach+0xb4/0xb8) [] (driver_detach) from [] (bus_remove_driver+0x4c/0xa0) [] (bus_remove_driver) from [] (SyS_delete_module+0x128/0x1cc) [] (SyS_delete_module) from [] (ret_fast_syscall+0x0/0x48) Signed-off-by: Ezequiel Garcia Acked-by: George Cherian With this I think it make sense to take the following patch also, to avoid unnecessary probe deferral http://www.spinics.net/lists/linux-usb/msg106202.html -- -George -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] ARM: dts: am33xx: Move the cppi41dma node so it's probed early
On 5/9/2014 12:55 PM, Sebastian Andrzej Siewior wrote: On 05/09/2014 08:22 AM, George Cherian wrote: Just by remodelling the dt the whole problem can be solved. I am still not convinced why we should not be doing it? Because neither ways its not the exact representation of the H/W. Ha. Now I am confused. First I assumed that the musb_am335x module is built-in only to duct-tape the bug you are seeing. So this patch never made it mainline then. The problem is as far as I remember the way the phy-core does things and should be fixed. Re-arranging does not help because you can still oops the kernel (the same oops you have now) by removing the devices manually via sysfs. Okay... So, You mean to say if I unbind the phy device and then try to remove musb_am335x module, then it will oops. Now I got it... Sebastian -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- -George -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH] ARM: dts: am33xx: Re-arrange the USB dt to reflect the h/w configuration
Re arrange the USB dt for AM33xx to take it a bit closer to the hardware configuration. The USBSS is designed as follows USB control Module 0x44e10_0620 USBSS 0x4740_ USB00x4740_1000 USB0_PHY0x4740_1300 USB0_CORE 0x4740_1400 USB10x4740_1800 USB1_PHY0x4740_1b00 USB1_CORE 0x4740_1c00 CPPI DMA Controller 0x4740_2000 CPPI DMA Scheduler 0x4740_3000 Queue Manager 0x4740_4000 So model the DT as follows USBSS { usb_ctrl_mod: { 0x44e10_0620 } usb0: { 0x4740_1000 0x4740_1400 } usb0_phy:{ 0x4740_1300 } usb1:{ 0x4740_1800 0x4740_1c00 } usb1_phy: { 0x4740_1b00 } cppi41dma: { 0x4740_2000 0x4740_3000 0x4740_4000 } } Signed-off-by: George Cherian --- arch/arm/boot/dts/am33xx.dtsi | 20 ++-- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi index cb6811e..d33a1e7 100644 --- a/arch/arm/boot/dts/am33xx.dtsi +++ b/arch/arm/boot/dts/am33xx.dtsi @@ -461,14 +461,6 @@ status = "disabled"; }; - usb0_phy: usb-phy@47401300 { - compatible = "ti,am335x-usb-phy"; - reg = <0x47401300 0x100>; - reg-names = "phy"; - status = "disabled"; - ti,ctrl_mod = <&usb_ctrl_mod>; - }; - usb0: usb@47401000 { compatible = "ti,musb-am33xx"; status = "disabled"; @@ -509,9 +501,9 @@ "tx14", "tx15"; }; - usb1_phy: usb-phy@47401b00 { + usb0_phy: usb-phy@47401300 { compatible = "ti,am335x-usb-phy"; - reg = <0x47401b00 0x100>; + reg = <0x47401300 0x100>; reg-names = "phy"; status = "disabled"; ti,ctrl_mod = <&usb_ctrl_mod>; @@ -556,6 +548,14 @@ "tx14", "tx15"; }; + usb1_phy: usb-phy@47401b00 { + compatible = "ti,am335x-usb-phy"; + reg = <0x47401b00 0x100>; + reg-names = "phy"; + status = "disabled"; + ti,ctrl_mod = <&usb_ctrl_mod>; + }; + cppi41dma: dma-controller@47402000 { compatible = "ti,am3359-cppi41"; reg = <0x4740 0x1000 -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] ARM: dts: am33xx: Move the cppi41dma node so it's probed early
On 5/8/2014 10:30 PM, Ezequiel GarcĂa wrote: Hi George, On 29 April 2014 04:58, George Cherian wrote: On 4/29/2014 11:49 AM, Yegor Yefremov wrote: On Thu, Apr 24, 2014 at 11:11 PM, Ezequiel Garcia wrote: The DMA controller is needed for the USB controller to be correctly registered. Therefore, if the DMA node is located at the end an unecessary probe deferral is produced systematically. This is easily fixed by moving the node at the beggining of the child list, so it's probed first. This will give issues on module removal. Since we use device_for_each_child in remove patch, it will try to remove cppi dma controller, while the channel is still in use by musb node. OK, this seems confusing: are you sure module removal works? No it does not . Doing this simple test on v3.15-rcN: $ modprobe musb_dsps $ modprobe musb_am335x $ modprobe musb_am335x -r And the kernel blows up :-( I've been debugging this and I think we simply cannot support removal of the musb_am335x module. Had this ever worked before Nope. I feel the whole problem is because how its modeled in dt. If you look at the TRM following are the memory maps for the USB modules USB control Module 0x44e10_0620 USBSS 0x4740_ USB0 0x4740_1000 USB0_PHY 0x4740_1300 USB0_CORE0x4740_1400 USB1 0x4740_1800 USB1_PHY 0x4740_1b00 USB1_CORE0x4740_1c00 CPPI DMA Controller 0x4740_2000 CPPI DMA Scheduler 0x4740_3000 Queue Manager 0x4740_4000 Now in the curent DT we have the follwoing USBSS { usb_ctrl_mod: { 0x44e10_0620 } usb0_phy:{ 0x4740_1300 } usb0: { 0x4740_1000 0x4740_1400 } usb1_phy: { 0x4740_1b00 } usb1:{ 0x4740_1800 0x4740_1c00 } cppi41dma: { 0x4740_2000 0x4740_3000 0x4740_4000 } } Just by remodelling the dt the whole problem can be solved. I am still not convinced why we should not be doing it? Because neither ways its not the exact representation of the H/W. I will send a patch as RFC for the same. -- -George -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 3/5] usb: musb: core: Convert the musb_platform_reset to have a return value.
On 5/8/2014 3:17 PM, Daniel Mack wrote: Hi Geroge, On 05/08/2014 11:35 AM, George Cherian wrote: -static inline void musb_platform_reset(struct musb *musb) +static inline int musb_platform_reset(struct musb *musb) { - if (musb->ops->reset) - musb->ops->reset(musb); + if (!musb->ops->reset) + return -EINVAL; + + return musb->ops->reset(musb); } static inline int musb_platform_get_vbus_status(struct musb *musb) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 74c4193..8438200 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -536,7 +536,7 @@ static int dsps_musb_set_mode(struct musb *musb, u8 mode) return 0; } -static void dsps_musb_reset(struct musb *musb) +static int dsps_musb_reset(struct musb *musb) { struct device *dev = musb->controller; struct dsps_glue *glue = dev_get_drvdata(dev->parent); @@ -548,6 +548,7 @@ static void dsps_musb_reset(struct musb *musb) usleep_range(100, 200); usb_phy_init(musb->xceiv); + return 1; Could we follow the general kernel rule here and return 0 for success, and < 0 on failure? I made this to return 1, just because the next patch in the series would make it return session_restart. Depending on which the musb_platform_reset() would return whether actual reset of IP (reset_done) is done or not . Thanks, Daniel -- -George -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 2/5] usb: musb: dsps: Call usb_phy(_shutdown/_init) during musb_platform_reset()
For DSPS platform usb_phy_vbus(_off/_on) are NOPs. So during musb_platform_reset() call usb_phy(_shutdown/_init) Signed-off-by: George Cherian --- drivers/usb/musb/musb_dsps.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 51beb13..74c4193 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -543,7 +543,11 @@ static void dsps_musb_reset(struct musb *musb) const struct dsps_musb_wrapper *wrp = glue->wrp; dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset)); - udelay(100); + usleep_range(100, 200); + usb_phy_shutdown(musb->xceiv); + usleep_range(100, 200); + usb_phy_init(musb->xceiv); + } static struct musb_platform_ops dsps_ops = { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 0/5] Add support for SW babble Control
Series add support for SW babble control logic found in new silicon versions of AM335x. Runtime differentiation of silicon version is done by checking the BABBLE_CTL register. For newer silicon the register default value read is 0x4 and for older versions its 0x0. Patch 1 -> Convert recover work to delayed work. Patch 2 -> usb_phy_vbus_(off/_on) are NOPs for am335x PHY so use usb_phy(_shutdown/_init) in musb_platform_reset() Patch 3 -> Add return value for musb_platform_reset() in prepration to support SW babble_ctrl Patch 4 -> Add the sw_babble_control() Patch 5 -> Enable sw babble control for newer silicon v1 -> v2 : Fixed the issue with Patch 5. In v1 it was not calling sw_babble_control(). George Cherian (5): usb: musb: core: Convert babble recover work to delayed work usb: musb: dsps: Call usb_phy(_shutdown/_init) during musb_platform_reset() usb: musb: core: Convert the musb_platform_reset to have a return value. usb: musb: dsps: Add the sw_babble_control() usb: musb: dsps: Enable sw babble control for newer silicon drivers/usb/musb/musb_core.c | 49 + drivers/usb/musb/musb_core.h | 12 --- drivers/usb/musb/musb_dsps.c | 85 ++-- drivers/usb/musb/musb_regs.h | 7 4 files changed, 124 insertions(+), 29 deletions(-) -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 5/5] usb: musb: dsps: Enable sw babble control for newer silicon
Find whether we are running on newer silicon. The babble control register reads 0x4 by default in newer silicon as opposed to 0 in old versions of AM335x. Based on this enable the sw babble control logic. Signed-off-by: George Cherian --- drivers/usb/musb/musb_dsps.c | 34 -- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 6647e7e..665d1dd 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -136,6 +136,7 @@ struct dsps_glue { const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */ struct timer_list timer;/* otg_workaround timer */ unsigned long last_timer;/* last timer data for each instance */ + bool sw_babble_enabled; struct dsps_context context; struct debugfs_regset32 regset; @@ -469,6 +470,16 @@ static int dsps_musb_init(struct musb *musb) val &= ~(1 << wrp->otg_disable); dsps_writel(musb->ctrl_base, wrp->phy_utmi, val); + /* +* Check whether the dsps version has babble control enabled. +* In latest silicon revision the babble control logic is enabled. +* If MUSB_BABBLE_CTL returns 0x4 then we have the babble control +* logic enabled. +*/ + val = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); + if (val == MUSB_BABBLE_RCV_DISABLE) + glue->sw_babble_enabled = true; + ret = dsps_musb_dbg_init(musb, glue); if (ret) return ret; @@ -591,14 +602,25 @@ static int dsps_musb_reset(struct musb *musb) struct device *dev = musb->controller; struct dsps_glue *glue = dev_get_drvdata(dev->parent); const struct dsps_musb_wrapper *wrp = glue->wrp; + int session_restart = 0; - dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset)); - usleep_range(100, 200); - usb_phy_shutdown(musb->xceiv); - usleep_range(100, 200); - usb_phy_init(musb->xceiv); + if (glue->sw_babble_enabled) + session_restart = sw_babble_control(musb); + /* +* In case of new silicon version babble condition can be recovered +* without resetting the MUSB. But for older silicon versions, MUSB +* reset is needed +*/ + if (session_restart || !glue->sw_babble_enabled) { + dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset)); + usleep_range(100, 200); + usb_phy_shutdown(musb->xceiv); + usleep_range(100, 200); + usb_phy_init(musb->xceiv); + session_restart = 1; + } - return 1; + return session_restart; } static struct musb_platform_ops dsps_ops = { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 3/5] usb: musb: core: Convert the musb_platform_reset to have a return value.
Currently musb_platform_reset() is only used by dsps. In case of BABBLE interrupt for other platforms the musb_platform_reset() is a NOP. In such situations no need to re-initialize the endpoints. Also in the latest silicon revision of AM335x, we do have a babble recovery mechanism without resetting the IP block. In preperation to add that support its better to have a rest_done return for musb_platform_reset(). Signed-off-by: George Cherian --- drivers/usb/musb/musb_core.c | 38 +- drivers/usb/musb/musb_core.h | 10 ++ drivers/usb/musb/musb_dsps.c | 3 ++- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index dcadc62..983a591 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1755,28 +1755,32 @@ static void musb_irq_work(struct work_struct *data) static void musb_recover_work(struct work_struct *data) { struct musb *musb = container_of(data, struct musb, recover_work.work); - int status; + int status, reset_done; - musb_platform_reset(musb); + reset_done = musb_platform_reset(musb); + if (reset_done < 0) + return; - usb_phy_vbus_off(musb->xceiv); - usleep_range(100, 200); + if (reset_done) { + usb_phy_vbus_off(musb->xceiv); + usleep_range(100, 200); - usb_phy_vbus_on(musb->xceiv); - usleep_range(100, 200); + usb_phy_vbus_on(musb->xceiv); + usleep_range(100, 200); - /* -* When a babble condition occurs, the musb controller removes the -* session bit and the endpoint config is lost. -*/ - if (musb->dyn_fifo) - status = ep_config_from_table(musb); - else - status = ep_config_from_hw(musb); + /* +* When a babble condition occurs, the musb controller removes the +* session bit and the endpoint config is lost. +*/ + if (musb->dyn_fifo) + status = ep_config_from_table(musb); + else + status = ep_config_from_hw(musb); - /* start the session again */ - if (status == 0) - musb_start(musb); + /* start the session again */ + if (status == 0) + musb_start(musb); + } } /* -- diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 423cd00..3ccb428 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -192,7 +192,7 @@ struct musb_platform_ops { int (*set_mode)(struct musb *musb, u8 mode); void(*try_idle)(struct musb *musb, unsigned long timeout); - void(*reset)(struct musb *musb); + int (*reset)(struct musb *musb); int (*vbus_status)(struct musb *musb); void(*set_vbus)(struct musb *musb, int on); @@ -554,10 +554,12 @@ static inline void musb_platform_try_idle(struct musb *musb, musb->ops->try_idle(musb, timeout); } -static inline void musb_platform_reset(struct musb *musb) +static inline int musb_platform_reset(struct musb *musb) { - if (musb->ops->reset) - musb->ops->reset(musb); + if (!musb->ops->reset) + return -EINVAL; + + return musb->ops->reset(musb); } static inline int musb_platform_get_vbus_status(struct musb *musb) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 74c4193..8438200 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -536,7 +536,7 @@ static int dsps_musb_set_mode(struct musb *musb, u8 mode) return 0; } -static void dsps_musb_reset(struct musb *musb) +static int dsps_musb_reset(struct musb *musb) { struct device *dev = musb->controller; struct dsps_glue *glue = dev_get_drvdata(dev->parent); @@ -548,6 +548,7 @@ static void dsps_musb_reset(struct musb *musb) usleep_range(100, 200); usb_phy_init(musb->xceiv); + return 1; } static struct musb_platform_ops dsps_ops = { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 1/5] usb: musb: core: Convert babble recover work to delayed work
During babble condition first disconnect of devices are initiated. Make sure MUSB controller is reset and re-initialized after all disconnects. To acheive this schedule a delayed work for babble rrecovery. While at that convert udelay to usleep_range. Refer Documentation/timers/timers-howto.txt Signed-off-by: George Cherian --- drivers/usb/musb/musb_core.c | 15 --- drivers/usb/musb/musb_core.h | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 61da471..dcadc62 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -850,7 +850,8 @@ b_host: /* handle babble condition */ if (int_usb & MUSB_INTR_BABBLE) - schedule_work(&musb->recover_work); + schedule_delayed_work(&musb->recover_work, + msecs_to_jiffies(100)); #if 0 /* REVISIT ... this would be for multiplexing periodic endpoints, or @@ -1753,16 +1754,16 @@ static void musb_irq_work(struct work_struct *data) /* Recover from babble interrupt conditions */ static void musb_recover_work(struct work_struct *data) { - struct musb *musb = container_of(data, struct musb, recover_work); + struct musb *musb = container_of(data, struct musb, recover_work.work); int status; musb_platform_reset(musb); usb_phy_vbus_off(musb->xceiv); - udelay(100); + usleep_range(100, 200); usb_phy_vbus_on(musb->xceiv); - udelay(100); + usleep_range(100, 200); /* * When a babble condition occurs, the musb controller removes the @@ -1945,7 +1946,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) /* Init IRQ workqueue before request_irq */ INIT_WORK(&musb->irq_work, musb_irq_work); - INIT_WORK(&musb->recover_work, musb_recover_work); + INIT_DELAYED_WORK(&musb->recover_work, musb_recover_work); INIT_DELAYED_WORK(&musb->deassert_reset_work, musb_deassert_reset); INIT_DELAYED_WORK(&musb->finish_resume_work, musb_host_finish_resume); @@ -2041,7 +2042,7 @@ fail4: fail3: cancel_work_sync(&musb->irq_work); - cancel_work_sync(&musb->recover_work); + cancel_delayed_work_sync(&musb->recover_work); cancel_delayed_work_sync(&musb->finish_resume_work); cancel_delayed_work_sync(&musb->deassert_reset_work); if (musb->dma_controller) @@ -2107,7 +2108,7 @@ static int musb_remove(struct platform_device *pdev) dma_controller_destroy(musb->dma_controller); cancel_work_sync(&musb->irq_work); - cancel_work_sync(&musb->recover_work); + cancel_delayed_work_sync(&musb->recover_work); cancel_delayed_work_sync(&musb->finish_resume_work); cancel_delayed_work_sync(&musb->deassert_reset_work); musb_free(musb); diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 47e8874..423cd00 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -297,7 +297,7 @@ struct musb { irqreturn_t (*isr)(int, void *); struct work_struct irq_work; - struct work_struct recover_work; + struct delayed_work recover_work; struct delayed_work deassert_reset_work; struct delayed_work finish_resume_work; u16 hwvers; -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 4/5] usb: musb: dsps: Add the sw_babble_control()
Add sw_babble_control() logic to differentiate between transient babble and real babble condition. Also add the SW babble control register definitions. Babble control register logic is implemented in the latest revision of AM335x. Signed-off-by: George Cherian --- drivers/usb/musb/musb_dsps.c | 50 drivers/usb/musb/musb_regs.h | 7 +++ 2 files changed, 57 insertions(+) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 8438200..6647e7e 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -536,6 +536,56 @@ static int dsps_musb_set_mode(struct musb *musb, u8 mode) return 0; } +static int sw_babble_control(struct musb *musb) +{ + int timeout = 10; + u8 babble_ctl, session_restart = 0; + + babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); + dev_dbg(musb->controller, "babble: MUSB_BABBLE_CTL value %x\n", + babble_ctl); + /* +* check line monitor flag to check whether babble is +* due to noise +*/ + dev_dbg(musb->controller, "STUCK_J is %s\n", + babble_ctl & MUSB_BABBLE_STUCK_J ? "set" : "reset"); + + if (babble_ctl & MUSB_BABBLE_STUCK_J) { + /* +* babble is due to noise, then set transmit idle (d7 bit) +* to resume normal operation +*/ + babble_ctl = musb_readb(musb->mregs, MUSB_BABBLE_CTL); + babble_ctl |= MUSB_BABBLE_FORCE_TXIDLE; + dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, babble_ctl); + + /* wait till line monitor flag cleared */ + dev_dbg(musb->controller, "Set TXIDLE, wait J to clear\n"); + do { + babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); + udelay(1); + } while ((babble_ctl & MUSB_BABBLE_STUCK_J) && timeout--); + + /* check whether stuck_at_j bit cleared */ + if (babble_ctl & MUSB_BABBLE_STUCK_J) { + /* +* real babble condition is occured +* restart the controller to start the +* session again +*/ + dev_dbg(musb->controller, "J not cleared, misc (%x)\n", + babble_ctl); + session_restart = 1; + } + + } else { + session_restart = 1; + } + + return session_restart; +} + static int dsps_musb_reset(struct musb *musb) { struct device *dev = musb->controller; diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h index 03f2655..b9bcda5 100644 --- a/drivers/usb/musb/musb_regs.h +++ b/drivers/usb/musb/musb_regs.h @@ -72,6 +72,12 @@ #define MUSB_DEVCTL_HR 0x02 #define MUSB_DEVCTL_SESSION0x01 +/* BABBLE_CTL */ +#define MUSB_BABBLE_FORCE_TXIDLE 0x80 +#define MUSB_BABBLE_SW_SESSION_CTRL0x40 +#define MUSB_BABBLE_STUCK_J0x20 +#define MUSB_BABBLE_RCV_DISABLE0x04 + /* MUSB ULPI VBUSCONTROL */ #define MUSB_ULPI_USE_EXTVBUS 0x01 #define MUSB_ULPI_USE_EXTVBUSIND 0x02 @@ -246,6 +252,7 @@ */ #define MUSB_DEVCTL0x60/* 8 bit */ +#define MUSB_BABBLE_CTL0x61/* 8 bit */ /* These are always controlled through the INDEX register */ #define MUSB_TXFIFOSZ 0x62/* 8-bit (see masks) */ -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/5] usb: dwc3: dwc3-omap: Add dwc3_omap_map_offset function
Calculate the wrapper register offsets in a seperate function. Improve code readability, decrease the dwc3_probe() size. Signed-off-by: George Cherian --- drivers/usb/dwc3/dwc3-omap.c | 80 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 1160ff4..872f065 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -383,6 +383,49 @@ static int dwc3_omap_vbus_notifier(struct notifier_block *nb, return NOTIFY_DONE; } +static void dwc3_omap_map_offset(struct dwc3_omap *omap) +{ + u32 reg; + struct device_node *node = omap->dev->of_node; + int x_major; + + reg = dwc3_omap_readl(omap->base, USBOTGSS_REVISION); + omap->revision = reg; + x_major = USBOTGSS_REVISION_XMAJOR(reg); + + /* Differentiate between OMAP5 and AM437x */ + switch (x_major) { + case USBOTGSS_REVISION_XMAJOR1: + case USBOTGSS_REVISION_XMAJOR2: + omap->irq_eoi_offset = 0; + omap->irq0_offset = 0; + omap->irqmisc_offset = 0; + omap->utmi_otg_offset = 0; + omap->debug_offset = 0; + break; + default: + /* Default to the latest revision */ + omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET; + omap->irq0_offset = USBOTGSS_IRQ0_OFFSET; + omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET; + omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET; + omap->debug_offset = USBOTGSS_DEBUG_OFFSET; + break; + } + + /* For OMAP5(ES2.0) and AM437x x_major is 2 even though there are +* changes in wrapper registers, Using dt compatible for aegis +*/ + + if (of_device_is_compatible(node, "ti,am437x-dwc3")) { + omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET; + omap->irq0_offset = USBOTGSS_IRQ0_OFFSET; + omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET; + omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET; + omap->debug_offset = USBOTGSS_DEBUG_OFFSET; + } +} + static int dwc3_omap_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -397,7 +440,6 @@ static int dwc3_omap_probe(struct platform_device *pdev) int irq; int utmi_mode = 0; - int x_major; u32 reg; @@ -448,41 +490,7 @@ static int dwc3_omap_probe(struct platform_device *pdev) goto err0; } - reg = dwc3_omap_readl(omap->base, USBOTGSS_REVISION); - omap->revision = reg; - x_major = USBOTGSS_REVISION_XMAJOR(reg); - - /* Differentiate between OMAP5 and AM437x */ - switch (x_major) { - case USBOTGSS_REVISION_XMAJOR1: - case USBOTGSS_REVISION_XMAJOR2: - omap->irq_eoi_offset = 0; - omap->irq0_offset = 0; - omap->irqmisc_offset = 0; - omap->utmi_otg_offset = 0; - omap->debug_offset = 0; - break; - default: - /* Default to the latest revision */ - omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET; - omap->irq0_offset = USBOTGSS_IRQ0_OFFSET; - omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET; - omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET; - omap->debug_offset = USBOTGSS_DEBUG_OFFSET; - break; - } - - /* For OMAP5(ES2.0) and AM437x x_major is 2 even though there are -* changes in wrapper registers, Using dt compatible for aegis -*/ - - if (of_device_is_compatible(node, "ti,am437x-dwc3")) { - omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET; - omap->irq0_offset = USBOTGSS_IRQ0_OFFSET; - omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET; - omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET; - omap->debug_offset = USBOTGSS_DEBUG_OFFSET; - } + dwc3_omap_map_offset(omap); reg = dwc3_omap_read_utmi_status(omap); -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/5] usb: dwc3: dwc3-omap: Add dwc3_omap_extcon_register function
Move the extcon related code to its own function. Improve code readability, decrease the dwc3_probe() size. Signed-off-by: George Cherian --- drivers/usb/dwc3/dwc3-omap.c | 65 ++-- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index b739a24..0b9b1d8 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -450,6 +450,42 @@ static void dwc3_omap_set_utmi_mode(struct dwc3_omap *omap) dwc3_omap_write_utmi_status(omap, reg); } +static int dwc3_omap_extcon_register(struct dwc3_omap *omap) +{ + u32 ret; + struct device_node *node = omap->dev->of_node; + struct extcon_dev *edev; + + if (of_property_read_bool(node, "extcon")) { + edev = extcon_get_edev_by_phandle(omap->dev, 0); + if (IS_ERR(edev)) { + dev_vdbg(omap->dev, "couldn't get extcon device\n"); + return -EPROBE_DEFER; + } + + omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier; + ret = extcon_register_interest(&omap->extcon_vbus_dev, + edev->name, "USB", + &omap->vbus_nb); + if (ret < 0) + dev_vdbg(omap->dev, "failed to register notifier for USB\n"); + + omap->id_nb.notifier_call = dwc3_omap_id_notifier; + ret = extcon_register_interest(&omap->extcon_id_dev, + edev->name, "USB-HOST", + &omap->id_nb); + if (ret < 0) + dev_vdbg(omap->dev, "failed to register notifier for USB-HOST\n"); + + if (extcon_get_cable_state(edev, "USB") == true) + dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID); + if (extcon_get_cable_state(edev, "USB-HOST") == true) + dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND); + } + + return 0; +} + static int dwc3_omap_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -457,7 +493,6 @@ static int dwc3_omap_probe(struct platform_device *pdev) struct dwc3_omap*omap; struct resource *res; struct device *dev = &pdev->dev; - struct extcon_dev *edev; struct regulator*vbus_reg = NULL; int ret = -ENOMEM; @@ -529,31 +564,9 @@ static int dwc3_omap_probe(struct platform_device *pdev) dwc3_omap_enable_irqs(omap); - if (of_property_read_bool(node, "extcon")) { - edev = extcon_get_edev_by_phandle(dev, 0); - if (IS_ERR(edev)) { - dev_vdbg(dev, "couldn't get extcon device\n"); - ret = -EPROBE_DEFER; - goto err2; - } - - omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier; - ret = extcon_register_interest(&omap->extcon_vbus_dev, - edev->name, "USB", &omap->vbus_nb); - if (ret < 0) - dev_vdbg(dev, "failed to register notifier for USB\n"); - omap->id_nb.notifier_call = dwc3_omap_id_notifier; - ret = extcon_register_interest(&omap->extcon_id_dev, edev->name, -"USB-HOST", &omap->id_nb); - if (ret < 0) - dev_vdbg(dev, - "failed to register notifier for USB-HOST\n"); - - if (extcon_get_cable_state(edev, "USB") == true) - dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID); - if (extcon_get_cable_state(edev, "USB-HOST") == true) - dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND); - } + ret = dwc3_omap_extcon_register(omap); + if (ret < 0) + goto err2; ret = of_platform_populate(node, NULL, NULL, dev); if (ret) { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/5] usb: dwc3: dwc3-omap: Add dwc3_omap_set_utmi_mode() function
Move find and set the utmi mode to its own seperate function. Improve code readability, decrease the dwc3_probe() size. Signed-off-by: George Cherian --- drivers/usb/dwc3/dwc3-omap.c | 44 +--- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 872f065..b739a24 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -426,6 +426,30 @@ static void dwc3_omap_map_offset(struct dwc3_omap *omap) } } +static void dwc3_omap_set_utmi_mode(struct dwc3_omap *omap) +{ + u32 reg; + struct device_node *node = omap->dev->of_node; + int utmi_mode = 0; + + reg = dwc3_omap_read_utmi_status(omap); + + of_property_read_u32(node, "utmi-mode", &utmi_mode); + + switch (utmi_mode) { + case DWC3_OMAP_UTMI_MODE_SW: + reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE; + break; + case DWC3_OMAP_UTMI_MODE_HW: + reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE; + break; + default: + dev_dbg(omap->dev, "UNKNOWN utmi mode %d\n", utmi_mode); + } + + dwc3_omap_write_utmi_status(omap, reg); +} + static int dwc3_omap_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -439,8 +463,6 @@ static int dwc3_omap_probe(struct platform_device *pdev) int ret = -ENOMEM; int irq; - int utmi_mode = 0; - u32 reg; void __iomem*base; @@ -491,23 +513,7 @@ static int dwc3_omap_probe(struct platform_device *pdev) } dwc3_omap_map_offset(omap); - - reg = dwc3_omap_read_utmi_status(omap); - - of_property_read_u32(node, "utmi-mode", &utmi_mode); - - switch (utmi_mode) { - case DWC3_OMAP_UTMI_MODE_SW: - reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE; - break; - case DWC3_OMAP_UTMI_MODE_HW: - reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE; - break; - default: - dev_dbg(dev, "UNKNOWN utmi mode %d\n", utmi_mode); - } - - dwc3_omap_write_utmi_status(omap, reg); + dwc3_omap_set_utmi_mode(omap); /* check the DMA Status */ reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG); -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 5/5] usb: dwc3: dwc3-omap: Disable/Enable core interrupts in Suspend/Resume
Enabling the core interrupts in complete is too late for XHCI, and stops xhci from proper operation. So remove prepare and complete and disable/enable interrupts in suspend/resume Signed-off-by: George Cherian --- drivers/usb/dwc3/dwc3-omap.c | 20 ++-- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 82b20d8f..0916c4b 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -622,27 +622,12 @@ static const struct of_device_id of_dwc3_match[] = { MODULE_DEVICE_TABLE(of, of_dwc3_match); #ifdef CONFIG_PM_SLEEP -static int dwc3_omap_prepare(struct device *dev) -{ - struct dwc3_omap*omap = dev_get_drvdata(dev); - - dwc3_omap_disable_irqs(omap); - - return 0; -} - -static void dwc3_omap_complete(struct device *dev) -{ - struct dwc3_omap*omap = dev_get_drvdata(dev); - - dwc3_omap_enable_irqs(omap); -} - static int dwc3_omap_suspend(struct device *dev) { struct dwc3_omap*omap = dev_get_drvdata(dev); omap->utmi_otg_status = dwc3_omap_read_utmi_status(omap); + dwc3_omap_disable_irqs(omap); return 0; } @@ -652,6 +637,7 @@ static int dwc3_omap_resume(struct device *dev) struct dwc3_omap*omap = dev_get_drvdata(dev); dwc3_omap_write_utmi_status(omap, omap->utmi_otg_status); + dwc3_omap_enable_irqs(omap); pm_runtime_disable(dev); pm_runtime_set_active(dev); @@ -661,8 +647,6 @@ static int dwc3_omap_resume(struct device *dev) } static const struct dev_pm_ops dwc3_omap_dev_pm_ops = { - .prepare= dwc3_omap_prepare, - .complete = dwc3_omap_complete, SET_SYSTEM_SLEEP_PM_OPS(dwc3_omap_suspend, dwc3_omap_resume) }; -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 4/5] usb: dwc3: dwc3-omap: Fix the crash on module removal
Following crash is seen on dwc3_omap removal Unable to handle kernel NULL pointer dereference at virtual address 0018 pgd = ec098000 [0018] *pgd=ad1f9831, *pte=, *ppte= Internal error: Oops: 17 [#1] SMP ARM Modules linked in: usb_f_ss_lb g_zero usb_f_acm u_serial usb_f_ecm u_ether libcomposite configfs snd_usb_audio snd_usbmidi_lib snd_rawmidi snd_hwdep snd_soc_omap snd_pcm_dmaengine snd_soc_core snd_compress snd_pcm snd_tim] CPU: 0 PID: 1296 Comm: rmmod Tainted: GW 3.15.0-rc4-02716-g95c4e18-dirty #10 task: ed05a080 ti: ec368000 task.ti: ec368000 PC is at release_resource+0x14/0x7c LR is at release_resource+0x10/0x7c pc : []lr : []psr: 6013 sp : ec369ec0 ip : 6013 fp : 00021008 r10: r9 : ec368000 r8 : c000e7a4 r7 : 0081 r6 : bf0062c0 r5 : ed7cd000 r4 : ed7d85c0 r3 : r2 : r1 : 0011 r0 : c086d08c Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user Control: 10c5387d Table: ac098059 DAC: 0015 Process rmmod (pid: 1296, stack limit = 0xec368248) Stack: (0xec369ec0 to 0xec36a000) 9ec0: 0001 ed7cd000 c034de94 ed7cd010 ed7cd000 c034e194 9ee0: bf0062cc ed7cd010 c03490b0 ed154cc0 ed4c2570 ed2b8410 ed156810 ed156810 bf006d24 c034db9c c034db84 c034c518 9f20: bf006d24 ed156810 bf006d24 c034cd2c bf006d24 bf006d68 0800 c034c340 9f40: c00a9e5c 0020 bf006d68 0800 ec369f4c 33637764 9f60: 616d6f5f 0070 0001 ec368000 ed05a080 c000e670 0001 c0084010 9f80: 00021088 0800 00021088 0081 8010 e6f4 00021088 0800 9fa0: 00021088 c000e5e0 00021088 0800 000210b8 0800 e04f6d00 e04f6d00 9fc0: 00021088 0800 00021088 0081 0001 be91de08 00021008 9fe0: 4d768880 be91dbb4 b6fc5984 4d76888c 8010 000210b8 [] (release_resource) from [] (platform_device_del+0x6c/0x9c) [] (platform_device_del) from [] (platform_device_unregister+0xc/0x18) [] (platform_device_unregister) from [] (dwc3_omap_remove_core+0xc/0x14 [dwc3_omap]) [] (dwc3_omap_remove_core [dwc3_omap]) from [] (device_for_each_child+0x34/0x74) [] (device_for_each_child) from [] (dwc3_omap_remove+0x6c/0x78 [dwc3_omap]) [] (dwc3_omap_remove [dwc3_omap]) from [] (platform_drv_remove+0x18/0x1c) [] (platform_drv_remove) from [] (__device_release_driver+0x70/0xc8) [] (__device_release_driver) from [] (driver_detach+0xb4/0xb8) [] (driver_detach) from [] (bus_remove_driver+0x4c/0x90) [] (bus_remove_driver) from [] (SyS_delete_module+0x10c/0x198) [] (SyS_delete_module) from [] (ret_fast_syscall+0x0/0x48) Code: e1a04000 e59f0068 eb14505e e5943010 (e5932018) ---[ end trace 7e2a8746ff4fc811 ]--- Segmentation fault Signed-off-by: George Cherian --- drivers/usb/dwc3/dwc3-omap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 0b9b1d8..82b20d8f 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -322,7 +322,7 @@ static int dwc3_omap_remove_core(struct device *dev, void *c) { struct platform_device *pdev = to_platform_device(dev); - platform_device_unregister(pdev); + of_device_unregister(pdev); return 0; } -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html