* [PATCH 1/2] musb: add musb support for AM35x
@ 2010-02-24 13:18 Ajay Kumar Gupta
[not found] ` <1267017527-17591-1-git-send-email-ajay.gupta-l0cyMroinI0@public.gmane.org>
0 siblings, 1 reply; 6+ messages in thread
From: Ajay Kumar Gupta @ 2010-02-24 13:18 UTC (permalink / raw)
To: linux-usb; +Cc: linux-omap, Ajay Kumar Gupta
AM35x has musb interface and uses CPPI4.1 DMA engine.
Current patch supports only PIO mode and there are on-going
discussions on location of CPPI4.1 DMA.
Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
---
drivers/usb/musb/Kconfig | 4 +-
drivers/usb/musb/Makefile | 4 +
drivers/usb/musb/am3517.c | 536 ++++++++++++++++++++++++++++++++++++++++++
drivers/usb/musb/musb_core.c | 3 +-
4 files changed, 544 insertions(+), 3 deletions(-)
create mode 100644 drivers/usb/musb/am3517.c
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index b4c783c..a29cf84 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -10,7 +10,7 @@ comment "Enable Host or Gadget support to see Inventra options"
config USB_MUSB_HDRC
depends on (USB || USB_GADGET)
depends on (ARM || (BF54x && !BF544) || (BF52x && !BF522 && !BF523))
- select NOP_USB_XCEIV if (ARCH_DAVINCI || MACH_OMAP3EVM || BLACKFIN)
+ select NOP_USB_XCEIV if (ARCH_DAVINCI || MACH_OMAP3EVM || BLACKFIN || MACH_OMAP3517EVM)
select TWL4030_USB if MACH_OMAP_3430SDP
select USB_OTG_UTILS
tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
@@ -140,7 +140,7 @@ config USB_MUSB_HDRC_HCD
config MUSB_PIO_ONLY
bool 'Disable DMA (always use PIO)'
depends on USB_MUSB_HDRC
- default y if USB_TUSB6010
+ default USB_TUSB6010 || MACH_OMAP3517EVM
help
All data is copied between memory and FIFO by the CPU.
DMA controllers are ignored.
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
index 85710cc..9263033 100644
--- a/drivers/usb/musb/Makefile
+++ b/drivers/usb/musb/Makefile
@@ -19,7 +19,11 @@ ifeq ($(CONFIG_ARCH_OMAP2430),y)
endif
ifeq ($(CONFIG_ARCH_OMAP3430),y)
+ ifeq ($(CONFIG_MACH_OMAP3517EVM),y)
+ musb_hdrc-objs += am3517.o
+ else
musb_hdrc-objs += omap2430.o
+ endif
endif
ifeq ($(CONFIG_BF54x),y)
diff --git a/drivers/usb/musb/am3517.c b/drivers/usb/musb/am3517.c
new file mode 100644
index 0000000..913a294
--- /dev/null
+++ b/drivers/usb/musb/am3517.c
@@ -0,0 +1,536 @@
+/*
+ * Texas Instruments AM3517 "glue layer"
+ *
+ * Copyright (c) 2010, by Texas Instruments
+ *
+ * Based on the DA8xx "glue layer" code.
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (c) 2008, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * This file is part of the Inventra Controller Driver for Linux.
+ *
+ * The Inventra Controller Driver for Linux is free software; you
+ * can redistribute it and/or modify it under the terms of the GNU
+ * General Public License version 2 as published by the Free Software
+ * Foundation.
+ *
+ * The Inventra Controller Driver for Linux 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 The Inventra Controller Driver for Linux ; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <plat/control.h>
+#include <plat/usb.h>
+
+#include "musb_core.h"
+
+/*
+ * AM3517 specific definitions
+ */
+
+/* CPPI 4.1 queue manager registers */
+#define QMGR_PEND0_REG 0x4090
+#define QMGR_PEND1_REG 0x4094
+#define QMGR_PEND2_REG 0x4098
+
+/* USB 2.0 PHY Control */
+#define CONF2_PHY_GPIOMODE (1 << 23)
+#define CONF2_OTGMODE (3 << 14)
+#define CONF2_SESENDEN (1 << 13)
+#define CONF2_VBDTCTEN (1 << 12)
+#define CONF2_REFFREQ_24MHZ (2 << 8)
+#define CONF2_REFFREQ_26MHZ (7 << 8)
+#define CONF2_REFFREQ_13MHZ (6 << 8)
+#define CONF2_REFFREQ (0xf << 8)
+#define CONF2_PHYCLKGD (1 << 7)
+#define CONF2_VBUSSENSE (1 << 6)
+#define CONF2_PHY_PLLON (1 << 5)
+#define CONF2_RESET (1 << 4)
+#define CONF2_PHYPWRDN (1 << 3)
+#define CONF2_OTGPWRDN (1 << 2)
+#define CONF2_DATPOL (1 << 1)
+
+
+#define AM3517_TX_EP_MASK 0xffff /* EP0 + 15 Tx EPs */
+#define AM3517_RX_EP_MASK 0xfffe /* 15 Rx EPs */
+
+#define AM3517_TX_INTR_MASK (AM3517_TX_EP_MASK << USB_INTR_TX_SHIFT)
+#define AM3517_RX_INTR_MASK (AM3517_RX_EP_MASK << USB_INTR_RX_SHIFT)
+
+#define A_WAIT_BCON_TIMEOUT 1100 /* in ms */
+
+static inline void phy_on(void)
+{
+ u32 devconf2;
+
+ /*
+ * Start the on-chip PHY and its PLL.
+ */
+ devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+
+ devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN |
+ CONF2_OTGMODE | CONF2_REFFREQ | CONF2_PHY_GPIOMODE);
+ devconf2 |= CONF2_SESENDEN | CONF2_VBDTCTEN | CONF2_PHY_PLLON |
+ CONF2_REFFREQ_13MHZ | CONF2_DATPOL;
+
+ omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+
+ DBG(1, "Waiting for PHY clock good...\n");
+ while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2)
+ & CONF2_PHYCLKGD))
+ cpu_relax();
+}
+
+static inline void phy_off(void)
+{
+ u32 devconf2;
+
+ /*
+ * Power down the on-chip PHY.
+ */
+ devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+
+ devconf2 &= ~CONF2_PHY_PLLON;
+ devconf2 |= CONF2_PHYPWRDN | CONF2_OTGPWRDN;
+ omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+}
+
+/**
+ * musb_platform_enable - enable interrupts
+ */
+void musb_platform_enable(struct musb *musb)
+{
+ void __iomem *reg_base = musb->ctrl_base;
+ u32 epmask, coremask;
+
+ /* Workaround: setup IRQs through both register sets. */
+ epmask = ((musb->epmask & AM3517_TX_EP_MASK) << USB_INTR_TX_SHIFT) |
+ ((musb->epmask & AM3517_RX_EP_MASK) << USB_INTR_RX_SHIFT);
+ coremask = (0x01ff << USB_INTR_USB_SHIFT);
+
+ musb_writel(reg_base, EP_INTR_MASK_SET_REG, epmask);
+ musb_writel(reg_base, CORE_INTR_MASK_SET_REG, coremask);
+
+ /* Force the DRVVBUS IRQ so we can start polling for ID change. */
+ if (is_otg_enabled(musb))
+ musb_writel(reg_base, CORE_INTR_SRC_SET_REG,
+ USB_INTR_DRVVBUS << USB_INTR_USB_SHIFT);
+}
+
+/**
+ * musb_platform_disable - disable HDRC and flush interrupts
+ */
+void musb_platform_disable(struct musb *musb)
+{
+ void __iomem *reg_base = musb->ctrl_base;
+
+ musb_writel(reg_base, CORE_INTR_MASK_CLEAR_REG, USB_INTR_USB_MASK);
+ musb_writel(reg_base, EP_INTR_MASK_CLEAR_REG,
+ AM3517_TX_INTR_MASK | AM3517_RX_INTR_MASK);
+ musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
+ musb_writel(reg_base, USB_END_OF_INTR_REG, 0);
+}
+
+static int vbus_state = -1;
+
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+#define portstate(stmt) stmt
+#else
+#define portstate(stmt)
+#endif
+
+static void am3517_source_power(struct musb *musb, int is_on, int immediate)
+{
+ if (is_on)
+ is_on = 1;
+
+ if (vbus_state == is_on)
+ return;
+ vbus_state = is_on;
+}
+
+static void am3517_set_vbus(struct musb *musb, int is_on)
+{
+ WARN_ON(is_on && is_peripheral_active(musb));
+ am3517_source_power(musb, is_on, 0);
+}
+
+#define POLL_SECONDS 2
+
+static struct timer_list otg_workaround;
+
+static void otg_timer(unsigned long _musb)
+{
+ struct musb *musb = (void *)_musb;
+ void __iomem *mregs = musb->mregs;
+ u8 devctl;
+ unsigned long flags;
+
+ /* We poll because AM3517's won't expose several OTG-critical
+ * status change events (from the transceiver) otherwise.
+ */
+ devctl = musb_readb(mregs, MUSB_DEVCTL);
+ DBG(7, "Poll devctl %02x (%s)\n", devctl, otg_state_string(musb));
+
+ spin_lock_irqsave(&musb->lock, flags);
+ switch (musb->xceiv->state) {
+ case OTG_STATE_A_WAIT_BCON:
+ devctl &= ~MUSB_DEVCTL_SESSION;
+ musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+ devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+ if (devctl & MUSB_DEVCTL_BDEVICE) {
+ musb->xceiv->state = OTG_STATE_B_IDLE;
+ MUSB_DEV_MODE(musb);
+ } else {
+ musb->xceiv->state = OTG_STATE_A_IDLE;
+ MUSB_HST_MODE(musb);
+ }
+ break;
+ case OTG_STATE_A_WAIT_VFALL:
+ /*
+ * Wait till VBUS falls below SessionEnd (~0.2 V); the 1.3
+ * RTL seems to mis-handle session "start" otherwise (or in
+ * our case "recover"), in routine "VBUS was valid by the time
+ * VBUSERR got reported during enumeration" cases.
+ */
+ if (devctl & MUSB_DEVCTL_VBUS) {
+ mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+ break;
+ }
+ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ musb_writel(musb->ctrl_base, CORE_INTR_SRC_SET_REG,
+ MUSB_INTR_VBUSERROR << USB_INTR_USB_SHIFT);
+ break;
+ case OTG_STATE_B_IDLE:
+ if (!is_peripheral_enabled(musb))
+ break;
+
+ /*
+ * There's no ID-changed IRQ, so we have no good way to tell
+ * when to switch to the A-Default state machine (by setting
+ * the DEVCTL.SESSION flag).
+ *
+ * Workaround: whenever we're in B_IDLE, try setting the
+ * session flag every few seconds. If it works, ID was
+ * grounded and we're now in the A-Default state machine.
+ *
+ * NOTE: setting the session flag is _supposed_ to trigger
+ * SRP but clearly it doesn't.
+ */
+ devctl = musb_readb(mregs, MUSB_DEVCTL);
+ if (devctl & MUSB_DEVCTL_BDEVICE)
+ mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+ else
+ musb->xceiv->state = OTG_STATE_A_IDLE;
+ break;
+ default:
+ break;
+ }
+ spin_unlock_irqrestore(&musb->lock, flags);
+}
+
+void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
+{
+ static unsigned long last_timer;
+
+ if (!is_otg_enabled(musb))
+ return;
+
+ if (timeout == 0)
+ timeout = jiffies + msecs_to_jiffies(3);
+
+ /* Never idle if active, or when VBUS timeout is not set as host */
+ if (musb->is_active || (musb->a_wait_bcon == 0 &&
+ musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
+ DBG(4, "%s active, deleting timer\n", otg_state_string(musb));
+ del_timer(&otg_workaround);
+ last_timer = jiffies;
+ return;
+ }
+
+ if (time_after(last_timer, timeout) && timer_pending(&otg_workaround)) {
+ DBG(4, "Longer idle timer already pending, ignoring...\n");
+ return;
+ }
+ last_timer = timeout;
+
+ DBG(4, "%s inactive, starting idle timer for %u ms\n",
+ otg_state_string(musb), jiffies_to_msecs(timeout - jiffies));
+ mod_timer(&otg_workaround, timeout);
+}
+
+static irqreturn_t am3517_interrupt(int irq, void *hci)
+{
+ struct musb *musb = hci;
+ void __iomem *reg_base = musb->ctrl_base;
+ unsigned long flags;
+ irqreturn_t ret = IRQ_NONE;
+ u32 epintr, usbintr, lvl_intr;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ /* Get endpoint interrupts */
+ epintr = musb_readl(reg_base, EP_INTR_SRC_MASKED_REG);
+
+ if (epintr) {
+ musb_writel(reg_base, EP_INTR_SRC_CLEAR_REG, epintr);
+
+ musb->int_rx =
+ (epintr & AM3517_RX_INTR_MASK) >> USB_INTR_RX_SHIFT;
+ musb->int_tx =
+ (epintr & AM3517_TX_INTR_MASK) >> USB_INTR_TX_SHIFT;
+ }
+
+ /* Get usb core interrupts */
+ usbintr = musb_readl(reg_base, CORE_INTR_SRC_MASKED_REG);
+ if (!usbintr && !epintr)
+ goto eoi;
+
+ if (usbintr) {
+ musb_writel(reg_base, CORE_INTR_SRC_CLEAR_REG, usbintr);
+
+ musb->int_usb =
+ (usbintr & USB_INTR_USB_MASK) >> USB_INTR_USB_SHIFT;
+ }
+ /*
+ * DRVVBUS IRQs are the only proxy we have (a very poor one!) for
+ * AM3517's missing ID change IRQ. We need an ID change IRQ to
+ * switch appropriately between halves of the OTG state machine.
+ * Managing DEVCTL.SESSION per Mentor docs requires that we know its
+ * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
+ * Also, DRVVBUS pulses for SRP (but not at 5V) ...
+ */
+ if (usbintr & (USB_INTR_DRVVBUS << USB_INTR_USB_SHIFT)) {
+ int drvvbus = musb_readl(reg_base, USB_STAT_REG);
+ void __iomem *mregs = musb->mregs;
+ u8 devctl = musb_readb(mregs, MUSB_DEVCTL);
+ int err;
+
+ err = is_host_enabled(musb) && (musb->int_usb &
+ MUSB_INTR_VBUSERROR);
+ if (err) {
+ /*
+ * The Mentor core doesn't debounce VBUS as needed
+ * to cope with device connect current spikes. This
+ * means it's not uncommon for bus-powered devices
+ * to get VBUS errors during enumeration.
+ *
+ * This is a workaround, but newer RTL from Mentor
+ * seems to allow a better one: "re"-starting sessions
+ * without waiting for VBUS to stop registering in
+ * devctl.
+ */
+ musb->int_usb &= ~MUSB_INTR_VBUSERROR;
+ musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
+ mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+ WARNING("VBUS error workaround (delay coming)\n");
+ } else if (is_host_enabled(musb) && drvvbus) {
+ musb->is_active = 1;
+ MUSB_HST_MODE(musb);
+ musb->xceiv->default_a = 1;
+ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ portstate(musb->port1_status |= USB_PORT_STAT_POWER);
+ del_timer(&otg_workaround);
+ } else {
+ musb->is_active = 0;
+ MUSB_DEV_MODE(musb);
+ musb->xceiv->default_a = 0;
+ musb->xceiv->state = OTG_STATE_B_IDLE;
+ portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
+ }
+
+ /* NOTE: this must complete power-on within 100 ms. */
+ am3517_source_power(musb, drvvbus, 0);
+ DBG(2, "VBUS %s (%s)%s, devctl %02x\n",
+ drvvbus ? "on" : "off",
+ otg_state_string(musb),
+ err ? " ERROR" : "",
+ devctl);
+ ret = IRQ_HANDLED;
+ }
+
+ if (musb->int_tx || musb->int_rx || musb->int_usb) {
+ irqreturn_t mret;
+
+ mret = musb_interrupt(musb);
+ if (mret == IRQ_HANDLED)
+ ret = IRQ_HANDLED;
+ }
+
+ eoi:
+ /* EOI needs to be written for the IRQ to be re-asserted. */
+ if (ret == IRQ_HANDLED || epintr || usbintr) {
+ /* clear level interrupt */
+ lvl_intr = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
+ lvl_intr |= AM35XX_USBOTGSS_INT_CLR;
+ omap_ctrl_writel(lvl_intr, AM35XX_CONTROL_LVL_INTR_CLEAR);
+ /* write EOI */
+ musb_writel(reg_base, USB_END_OF_INTR_REG, 0);
+ }
+
+ /* Poll for ID change */
+ if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE)
+ mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ if (ret != IRQ_HANDLED) {
+ if (epintr || usbintr)
+ /*
+ * We sometimes get unhandled IRQs in the peripheral
+ * mode from EP0 and SOF...
+ */
+ DBG(2, "Unhandled USB IRQ %08x-%08x\n",
+ epintr, usbintr);
+ else if (printk_ratelimit())
+ /*
+ * We've seen series of spurious interrupts in the
+ * peripheral mode after USB reset and then after some
+ * time a real interrupt storm starting...
+ */
+ DBG(2, "Spurious IRQ\n");
+ }
+ return ret;
+}
+
+int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
+{
+ WARNING("FIXME: %s not implemented\n", __func__);
+ return -EIO;
+}
+
+int __init musb_platform_init(struct musb *musb)
+{
+ void __iomem *reg_base = musb->ctrl_base;
+ struct clk *otg_fck;
+ u32 rev, lvl_intr, sw_reset;
+
+ usb_nop_xceiv_register();
+
+ musb->xceiv = otg_get_transceiver();
+ if (!musb->xceiv)
+ return -ENODEV;
+
+ /* Mentor is at offset of 0x400 in AM3517 */
+ musb->mregs += USB_MENTOR_CORE_OFFSET;
+
+ /* musb->clock is already set from board/arch files */
+ if (IS_ERR(musb->clock))
+ return PTR_ERR(musb->clock);
+
+ if (musb->set_clock)
+ musb->set_clock(musb->clock, 1);
+ else
+ clk_enable(musb->clock);
+
+ DBG(2, "usbotg_ck=%lud\n", clk_get_rate(musb->clock));
+ otg_fck = clk_get(musb->controller, "fck");
+ clk_enable(otg_fck);
+
+ DBG(2, "usbotg_phy_ck=%lud\n", clk_get_rate(otg_fck));
+ /* Returns zero if e.g. not clocked */
+ rev = musb_readl(reg_base, USB_REVISION_REG);
+ if (!rev)
+ return -ENODEV;
+
+ if (is_host_enabled(musb))
+ setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);
+
+ musb->board_set_vbus = am3517_set_vbus;
+ am3517_source_power(musb, 0, 1);
+
+ /* global reset */
+ sw_reset = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
+
+ sw_reset |= AM35XX_USBOTGSS_SW_RST;
+ omap_ctrl_writel(sw_reset, AM35XX_CONTROL_IP_SW_RESET);
+
+ sw_reset &= ~AM35XX_USBOTGSS_SW_RST;
+ omap_ctrl_writel(sw_reset, AM35XX_CONTROL_IP_SW_RESET);
+
+ /* Reset the controller */
+ musb_writel(reg_base, USB_CTRL_REG, USB_SOFT_RESET_MASK);
+
+ /* Start the on-chip PHY and its PLL. */
+ phy_on();
+
+ msleep(15);
+
+ musb->a_wait_bcon = A_WAIT_BCON_TIMEOUT;
+ musb->isr = am3517_interrupt;
+
+ /* clear level interrupt */
+ lvl_intr = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
+ lvl_intr |= AM35XX_USBOTGSS_INT_CLR;
+ omap_ctrl_writel(lvl_intr, AM35XX_CONTROL_LVL_INTR_CLEAR);
+
+ return 0;
+}
+
+int musb_platform_exit(struct musb *musb)
+{
+ if (is_host_enabled(musb))
+ del_timer_sync(&otg_workaround);
+
+ am3517_source_power(musb, 0 /* off */, 1);
+
+ /* Delay to avoid problems with module reload... */
+ if (is_host_enabled(musb) && musb->xceiv->default_a) {
+ int maxdelay = 30;
+ u8 devctl, warn = 0;
+
+ /*
+ * If there's no peripheral connected, this can take a
+ * long time to fall...
+ */
+ do {
+ devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+ if (!(devctl & MUSB_DEVCTL_VBUS))
+ break;
+ if ((devctl & MUSB_DEVCTL_VBUS) != warn) {
+ warn = devctl & MUSB_DEVCTL_VBUS;
+ DBG(1, "VBUS %d\n",
+ warn >> MUSB_DEVCTL_VBUS_SHIFT);
+ }
+ msleep(1000);
+ maxdelay--;
+ } while (maxdelay > 0);
+
+ /* In OTG mode, another host might be connected... */
+ if (devctl & MUSB_DEVCTL_VBUS)
+ DBG(1, "VBUS off timeout (devctl %02x)\n", devctl);
+ }
+
+ phy_off();
+
+ usb_nop_xceiv_unregister();
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+void musb_platform_save_context(struct musb_context_registers
+ *musb_context)
+{
+ phy_off();
+}
+
+void musb_platform_restore_context(struct musb_context_registers
+ *musb_context)
+{
+ phy_on();
+}
+#endif
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 98fd5b6..f8efe00 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -982,7 +982,8 @@ static void musb_shutdown(struct platform_device *pdev)
* more than selecting one of a bunch of predefined configurations.
*/
#if defined(CONFIG_USB_TUSB6010) || \
- defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3)
+ defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
+ defined(CONFIG_MACH_OMAP3517EVM)
static ushort __initdata fifo_mode = 4;
#else
static ushort __initdata fifo_mode = 2;
--
1.6.2.4
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/2] AM35x: musb: Workaround for fifo read issue
[not found] ` <1267017527-17591-1-git-send-email-ajay.gupta-l0cyMroinI0@public.gmane.org>
@ 2010-02-24 13:18 ` Ajay Kumar Gupta
2010-03-12 14:56 ` [PATCH 1/2] musb: add musb support for AM35x Sergei Shtylyov
2010-03-12 15:04 ` Sergei Shtylyov
2 siblings, 0 replies; 6+ messages in thread
From: Ajay Kumar Gupta @ 2010-02-24 13:18 UTC (permalink / raw)
To: linux-usb-u79uwXL29TY76Z2rM5mHXA
Cc: linux-omap-u79uwXL29TY76Z2rM5mHXA, Ajay Kumar Gupta
AM35x supports only 32bit read operations so we need to have
workaround for 8bit and 16bit read operations.
Signed-off-by: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org>
---
drivers/usb/musb/am3517.c | 30 ++++++++++++++++++++++++++++++
drivers/usb/musb/musb_core.c | 2 ++
2 files changed, 32 insertions(+), 0 deletions(-)
diff --git a/drivers/usb/musb/am3517.c b/drivers/usb/musb/am3517.c
index 913a294..1326089 100644
--- a/drivers/usb/musb/am3517.c
+++ b/drivers/usb/musb/am3517.c
@@ -534,3 +534,33 @@ void musb_platform_restore_context(struct musb_context_registers
phy_on();
}
#endif
+
+/* AM35x supports only 32bit read operation */
+void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
+{
+ void __iomem *fifo = hw_ep->fifo;
+ u32 val;
+ int i;
+
+ /* Read for 32bit-aligned destination address */
+ if ((likely((0x03 & (unsigned long) dst) == 0)) && len >= 4) {
+ readsl(fifo, dst, len >> 2);
+ dst += (len & ~0x03);
+ len &= 0x03;
+ }
+ /* Now read the rest 1 to 3 bytes or complete length if
+ * unaligned address.
+ */
+ if (len > 4) {
+ for (i = 0; i < (len >> 2); i++) {
+ val = musb_readl(fifo, 0);
+ memcpy(dst, &val, 4);
+ dst += 4;
+ }
+ len %= 4;
+ }
+ if (len > 0) {
+ val = musb_readl(fifo, 0);
+ memcpy(dst, &val, len);
+ }
+}
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index f8efe00..2c1b3ab 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -191,6 +191,7 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src)
}
}
+#if !defined(CONFIG_MACH_OMAP3517EVM)
/*
* Unload an endpoint's FIFO
*/
@@ -228,6 +229,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
readsb(fifo, dst, len);
}
}
+#endif
#endif /* normal PIO */
--
1.6.2.4
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] musb: add musb support for AM35x
[not found] ` <1267017527-17591-1-git-send-email-ajay.gupta-l0cyMroinI0@public.gmane.org>
2010-02-24 13:18 ` [PATCH 2/2] AM35x: musb: Workaround for fifo read issue Ajay Kumar Gupta
@ 2010-03-12 14:56 ` Sergei Shtylyov
[not found] ` <4B9A560B.7010908-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
2010-03-12 15:04 ` Sergei Shtylyov
2 siblings, 1 reply; 6+ messages in thread
From: Sergei Shtylyov @ 2010-03-12 14:56 UTC (permalink / raw)
To: Ajay Kumar Gupta
Cc: linux-usb-u79uwXL29TY76Z2rM5mHXA,
linux-omap-u79uwXL29TY76Z2rM5mHXA
Hello.
Ajay Kumar Gupta wrote:
> AM35x has musb interface and uses CPPI4.1 DMA engine.
> Current patch supports only PIO mode and there are on-going
> discussions on location of CPPI4.1 DMA.
>
> Signed-off-by: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org>
> ---
> drivers/usb/musb/Kconfig | 4 +-
> drivers/usb/musb/Makefile | 4 +
> drivers/usb/musb/am3517.c | 536 ++++++++++++++++++++++++++++++++++++++++++
> drivers/usb/musb/musb_core.c | 3 +-
> 4 files changed, 544 insertions(+), 3 deletions(-)
> create mode 100644 drivers/usb/musb/am3517.c
>
> diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
> index b4c783c..a29cf84 100644
> --- a/drivers/usb/musb/Kconfig
> +++ b/drivers/usb/musb/Kconfig
> @@ -10,7 +10,7 @@ comment "Enable Host or Gadget support to see Inventra options"
> config USB_MUSB_HDRC
> depends on (USB || USB_GADGET)
> depends on (ARM || (BF54x && !BF544) || (BF52x && !BF522 && !BF523))
> - select NOP_USB_XCEIV if (ARCH_DAVINCI || MACH_OMAP3EVM || BLACKFIN)
> + select NOP_USB_XCEIV if (ARCH_DAVINCI || MACH_OMAP3EVM || BLACKFIN || MACH_OMAP3517EVM)
> select TWL4030_USB if MACH_OMAP_3430SDP
> select USB_OTG_UTILS
> tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
> @@ -140,7 +140,7 @@ config USB_MUSB_HDRC_HCD
> config MUSB_PIO_ONLY
> bool 'Disable DMA (always use PIO)'
> depends on USB_MUSB_HDRC
> - default y if USB_TUSB6010
> + default USB_TUSB6010 || MACH_OMAP3517EVM
> help
> All data is copied between memory and FIFO by the CPU.
> DMA controllers are ignored.
> diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
> index 85710cc..9263033 100644
> --- a/drivers/usb/musb/Makefile
> +++ b/drivers/usb/musb/Makefile
> @@ -19,7 +19,11 @@ ifeq ($(CONFIG_ARCH_OMAP2430),y)
> endif
>
> ifeq ($(CONFIG_ARCH_OMAP3430),y)
> + ifeq ($(CONFIG_MACH_OMAP3517EVM),y)
> + musb_hdrc-objs += am3517.o
>
Isn't there some ARCH-level option for AM3517 SoC? Depending on the
board type doesn't really scale well...
> + else
> musb_hdrc-objs += omap2430.o
> + endif
> endif
>
> ifeq ($(CONFIG_BF54x),y)
> diff --git a/drivers/usb/musb/am3517.c b/drivers/usb/musb/am3517.c
> new file mode 100644
> index 0000000..913a294
> --- /dev/null
> +++ b/drivers/usb/musb/am3517.c
> @@ -0,0 +1,536 @@
>
[...]
> +/*
> + * AM3517 specific definitions
> + */
> +
> +/* CPPI 4.1 queue manager registers */
> +#define QMGR_PEND0_REG 0x4090
> +#define QMGR_PEND1_REG 0x4094
> +#define QMGR_PEND2_REG 0x4098
>
Those are not used (yet)...
> +static inline void phy_on(void)
> +{
> + u32 devconf2;
> +
> + /*
> + * Start the on-chip PHY and its PLL.
> + */
> + devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
> +
> + devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN |
> + CONF2_OTGMODE | CONF2_REFFREQ | CONF2_PHY_GPIOMODE);
>
Shouldn't you manipulate CONF2_OTGMODE in the board code instead? I
suspect value of 0 doesn't fit the host-only configuration (without
cable connected, MUSB will think it's a B-device, and the driver will
fail to initialize IIRC).
> + devconf2 |= CONF2_SESENDEN | CONF2_VBDTCTEN | CONF2_PHY_PLLON |
> + CONF2_REFFREQ_13MHZ | CONF2_DATPOL;
>
Reference clock of 13 MHz, not 12? Hmm... Again, shouldn't the board
code select the reference frequency (clock might be external, IIUC)?
> +static inline void phy_off(void)
> +{
> + u32 devconf2;
> +
> + /*
> + * Power down the on-chip PHY.
> + */
> + devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
> +
> + devconf2 &= ~CONF2_PHY_PLLON;
> + devconf2 |= CONF2_PHYPWRDN | CONF2_OTGPWRDN;
> + omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
> +}
> +
> +/**
> + * musb_platform_enable - enable interrupts
> + */
> +void musb_platform_enable(struct musb *musb)
> +{
> + void __iomem *reg_base = musb->ctrl_base;
> + u32 epmask, coremask;
> +
> + /* Workaround: setup IRQs through both register sets. */
> + epmask = ((musb->epmask & AM3517_TX_EP_MASK) << USB_INTR_TX_SHIFT) |
> + ((musb->epmask & AM3517_RX_EP_MASK) << USB_INTR_RX_SHIFT);
> + coremask = (0x01ff << USB_INTR_USB_SHIFT);
> +
> + musb_writel(reg_base, EP_INTR_MASK_SET_REG, epmask);
> + musb_writel(reg_base, CORE_INTR_MASK_SET_REG, coremask);
>
Hm, and I thought all CPPI 4.1 based controllers have the same
register layout... alas, I was wrong.
> +static int vbus_state = -1;
>
[...]
> +static void am3517_source_power(struct musb *musb, int is_on, int immediate)
> +{
> + if (is_on)
> + is_on = 1;
> +
> + if (vbus_state == is_on)
> + return;
> + vbus_state = is_on;
> +}
> +
>
Without the real GPIOs to manipulate, I don't understand the purpose
of this function...
> +static struct timer_list otg_workaround;
> +
> +static void otg_timer(unsigned long _musb)
> +{
> + struct musb *musb = (void *)_musb;
> + void __iomem *mregs = musb->mregs;
> + u8 devctl;
> + unsigned long flags;
> +
> + /* We poll because AM3517's won't expose several OTG-critical
> + * status change events (from the transceiver) otherwise.
>
Need one more space before *...
> + case OTG_STATE_A_WAIT_VFALL:
> + /*
> + * Wait till VBUS falls below SessionEnd (~0.2 V); the 1.3
> + * RTL seems to mis-handle session "start" otherwise (or in
> + * our case "recover"), in routine "VBUS was valid by the time
> + * VBUSERR got reported during enumeration" cases.
> + */
>
I wonder if all this still true for RTL 1.8 on which DA8xx (and
probably AM3517) MUSB is based...
> +void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
> +{
>
I wonder how DaVinci gets about without musb_platfrom_try_idle()...
> +static irqreturn_t am3517_interrupt(int irq, void *hci)
> +{
> + /* NOTE: this must complete power-on within 100 ms. */
> + am3517_source_power(musb, drvvbus, 0);
>
This call is effectively a NOP.
> + if (musb->int_tx || musb->int_rx || musb->int_usb) {
> + irqreturn_t mret;
> +
> + mret = musb_interrupt(musb);
> + if (mret == IRQ_HANDLED)
> + ret = IRQ_HANDLED;
>
Not sure why you didn't like ret |= musb_interrupt(musb)...
> + if (ret != IRQ_HANDLED) {
> + if (epintr || usbintr)
> + /*
> + * We sometimes get unhandled IRQs in the peripheral
> + * mode from EP0 and SOF...
> + */
> + DBG(2, "Unhandled USB IRQ %08x-%08x\n",
> + epintr, usbintr);
>
This check shouldn't be needed any more -- EP0 spurious interrupts
have been all chased down...
> + else if (printk_ratelimit())
> + /*
> + * We've seen series of spurious interrupts in the
> + * peripheral mode after USB reset and then after some
> + * time a real interrupt storm starting...
> + */
> + DBG(2, "Spurious IRQ\n");
>
Those turned out to be interrupts caused by CPPI 4.1 descriptor
starvation (for which the controller didn't even have an interrupt bit).
I still haven't dealt with them...
> + }
> + return ret;
> +}
> +
> +int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
> +{
> + WARNING("FIXME: %s not implemented\n", __func__);
> + return -EIO;
>
Could be implemented using CONF2_OTGMODE...
> +int __init musb_platform_init(struct musb *musb)
> +{
> + void __iomem *reg_base = musb->ctrl_base;
> + struct clk *otg_fck;
> + u32 rev, lvl_intr, sw_reset;
> +
> + usb_nop_xceiv_register();
> +
> + musb->xceiv = otg_get_transceiver();
> + if (!musb->xceiv)
> + return -ENODEV;
> +
> + /* Mentor is at offset of 0x400 in AM3517 */
> + musb->mregs += USB_MENTOR_CORE_OFFSET;
> +
> + /* musb->clock is already set from board/arch files */
> + if (IS_ERR(musb->clock))
> + return PTR_ERR(musb->clock);
>
This is checked by musb_core.c now, no need to duplicate...
> + if (musb->set_clock)
> + musb->set_clock(musb->clock, 1);
>
musb->set_clock() is about to be dropped...
> + else
> + clk_enable(musb->clock);
> +
> + DBG(2, "usbotg_ck=%lud\n", clk_get_rate(musb->clock));
>
I'd put an empty line after that DBG() rather than before.
> + otg_fck = clk_get(musb->controller, "fck");
> + clk_enable(otg_fck);
>
Oh, it needs two clocks... Another argument against Felipe dropping
plat->clock. :-)
> +
> + DBG(2, "usbotg_phy_ck=%lud\n", clk_get_rate(otg_fck));
>
Same about empty line here...
> + am3517_source_power(musb, 0, 1);
>
Effective NOP...
> + /* Start the on-chip PHY and its PLL. */
> + phy_on();
> +
> + msleep(15);
>
5 ms is not enough?
> + musb->a_wait_bcon = A_WAIT_BCON_TIMEOUT;
>
Hm... that line kept causing a stream of kernel messages for me,
until I removed it. Doesn't it for you?
> diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
> index 98fd5b6..f8efe00 100644
> --- a/drivers/usb/musb/musb_core.c
> +++ b/drivers/usb/musb/musb_core.c
> @@ -982,7 +982,8 @@ static void musb_shutdown(struct platform_device *pdev)
> * more than selecting one of a bunch of predefined configurations.
> */
> #if defined(CONFIG_USB_TUSB6010) || \
> - defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3)
> + defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
> + defined(CONFIG_MACH_OMAP3517EVM)
>
Isn't that dependency already covered by CONFIG_ARCH_OMAP3? Or else I
don't see you adding your #ifdef around musb_platfrom_try_idle()
declaration...
WBR, Sergei
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] musb: add musb support for AM35x
[not found] ` <1267017527-17591-1-git-send-email-ajay.gupta-l0cyMroinI0@public.gmane.org>
2010-02-24 13:18 ` [PATCH 2/2] AM35x: musb: Workaround for fifo read issue Ajay Kumar Gupta
2010-03-12 14:56 ` [PATCH 1/2] musb: add musb support for AM35x Sergei Shtylyov
@ 2010-03-12 15:04 ` Sergei Shtylyov
2 siblings, 0 replies; 6+ messages in thread
From: Sergei Shtylyov @ 2010-03-12 15:04 UTC (permalink / raw)
To: Ajay Kumar Gupta
Cc: linux-usb-u79uwXL29TY76Z2rM5mHXA,
linux-omap-u79uwXL29TY76Z2rM5mHXA
Ajay Kumar Gupta wrote:
> AM35x has musb interface and uses CPPI4.1 DMA engine.
> Current patch supports only PIO mode and there are on-going
> discussions on location of CPPI4.1 DMA.
>
> Signed-off-by: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org>
Overlooked one thing...
[...]
> +int musb_platform_exit(struct musb *musb)
> +{
>
[...]
> + phy_off();
> +
> + usb_nop_xceiv_unregister();
> +
> + return 0;
>
You forgot the calls to clk_disable() for both your clocks...
> +}
> +
>
WBR, Sergei
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [PATCH 1/2] musb: add musb support for AM35x
[not found] ` <4B9A560B.7010908-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
@ 2010-03-15 5:10 ` Gupta, Ajay Kumar
2010-03-26 19:29 ` Sergei Shtylyov
0 siblings, 1 reply; 6+ messages in thread
From: Gupta, Ajay Kumar @ 2010-03-15 5:10 UTC (permalink / raw)
To: Sergei Shtylyov
Cc: linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-omap-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Hi,
> > AM35x has musb interface and uses CPPI4.1 DMA engine.
> > Current patch supports only PIO mode and there are on-going
> > discussions on location of CPPI4.1 DMA.
> >
> > Signed-off-by: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org>
> > tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
> > @@ -140,7 +140,7 @@ config USB_MUSB_HDRC_HCD
> > config MUSB_PIO_ONLY
> > bool 'Disable DMA (always use PIO)'
> > depends on USB_MUSB_HDRC
> > - default y if USB_TUSB6010
> > + default USB_TUSB6010 || MACH_OMAP3517EVM
> > help
> > All data is copied between memory and FIFO by the CPU.
> > DMA controllers are ignored.
> > diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
> > index 85710cc..9263033 100644
> > --- a/drivers/usb/musb/Makefile
> > +++ b/drivers/usb/musb/Makefile
> > @@ -19,7 +19,11 @@ ifeq ($(CONFIG_ARCH_OMAP2430),y)
> > endif
> >
> > ifeq ($(CONFIG_ARCH_OMAP3430),y)
> > + ifeq ($(CONFIG_MACH_OMAP3517EVM),y)
> > + musb_hdrc-objs += am3517.o
> >
>
> Isn't there some ARCH-level option for AM3517 SoC? Depending on the
> board type doesn't really scale well...
AM3517 is actually based on OMAP3 but musb is different. Unfortunately there
is no seperate *_ARCH_* defines for AM3517 alone.
> > + * AM3517 specific definitions
> > + */
> > +
> > +/* CPPI 4.1 queue manager registers */
> > +#define QMGR_PEND0_REG 0x4090
> > +#define QMGR_PEND1_REG 0x4094
> > +#define QMGR_PEND2_REG 0x4098
> >
>
> Those are not used (yet)...
Yes, but I added them as they are part of register layout.
>
> > +static inline void phy_on(void)
> > +{
> > + u32 devconf2;
> > +
> > + /*
> > + * Start the on-chip PHY and its PLL.
> > + */
> > + devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
> > +
> > + devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN |
> > + CONF2_OTGMODE | CONF2_REFFREQ | CONF2_PHY_GPIOMODE);
> >
>
> Shouldn't you manipulate CONF2_OTGMODE in the board code instead? I
> suspect value of 0 doesn't fit the host-only configuration (without
> cable connected, MUSB will think it's a B-device, and the driver will
> fail to initialize IIRC).
I didn't see any issue in Host/Device only and OTG mode configurations
On AM3517? Did you see any issue on DA8xx?
>
> > + devconf2 |= CONF2_SESENDEN | CONF2_VBDTCTEN | CONF2_PHY_PLLON |
> > + CONF2_REFFREQ_13MHZ | CONF2_DATPOL;
> >
>
> Reference clock of 13 MHz, not 12? Hmm... Again, shouldn't the board
> code select the reference frequency (clock might be external, IIUC)?
Yeah, it's 13Mhz.Clock setting from board would be good to have though
Currently there is only one board AM3517EVM.
> > +/**
> > + * musb_platform_enable - enable interrupts
> > + */
> > +void musb_platform_enable(struct musb *musb)
> > +{
> > + void __iomem *reg_base = musb->ctrl_base;
> > + u32 epmask, coremask;
> > +
> > + /* Workaround: setup IRQs through both register sets. */
> > + epmask = ((musb->epmask & AM3517_TX_EP_MASK) << USB_INTR_TX_SHIFT) |
> > + ((musb->epmask & AM3517_RX_EP_MASK) << USB_INTR_RX_SHIFT);
> > + coremask = (0x01ff << USB_INTR_USB_SHIFT);
> > +
> > + musb_writel(reg_base, EP_INTR_MASK_SET_REG, epmask);
> > + musb_writel(reg_base, CORE_INTR_MASK_SET_REG, coremask);
> >
>
> Hm, and I thought all CPPI 4.1 based controllers have the same
> register layout... alas, I was wrong.
There are changes as AM3517 supports 15Rx/Tx endpoints.
>
> > +static int vbus_state = -1;
> >
> [...]
> > +static void am3517_source_power(struct musb *musb, int is_on, int
> immediate)
> > +{
> > + if (is_on)
> > + is_on = 1;
> > +
> > + if (vbus_state == is_on)
> > + return;
> > + vbus_state = is_on;
> > +}
> > +
> >
>
> Without the real GPIOs to manipulate, I don't understand the purpose
> of this function...
Correct, this function can be removed.
>
> > +static struct timer_list otg_workaround;
> > +
> > +static void otg_timer(unsigned long _musb)
> > +{
> > + struct musb *musb = (void *)_musb;
> > + void __iomem *mregs = musb->mregs;
> > + u8 devctl;
> > + unsigned long flags;
> > +
> > + /* We poll because AM3517's won't expose several OTG-critical
> > + * status change events (from the transceiver) otherwise.
> >
>
> Need one more space before *...
Right.
>
> > + case OTG_STATE_A_WAIT_VFALL:
> > + /*
> > + * Wait till VBUS falls below SessionEnd (~0.2 V); the 1.3
> > + * RTL seems to mis-handle session "start" otherwise (or in
> > + * our case "recover"), in routine "VBUS was valid by the time
> > + * VBUSERR got reported during enumeration" cases.
> > + */
> >
>
> I wonder if all this still true for RTL 1.8 on which DA8xx (and
> probably AM3517) MUSB is based...
Need to check on this..though I didn't see any issue in my testing.
>
> > +void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
> > +{
> >
>
> I wonder how DaVinci gets about without musb_platfrom_try_idle()...
Hmm..
>
> > +static irqreturn_t am3517_interrupt(int irq, void *hci)
> > +{
>
> > + /* NOTE: this must complete power-on within 100 ms. */
> > + am3517_source_power(musb, drvvbus, 0);
> >
>
> This call is effectively a NOP.
Yes and so should be removed.
>
> > + if (musb->int_tx || musb->int_rx || musb->int_usb) {
> > + irqreturn_t mret;
> > +
> > + mret = musb_interrupt(musb);
> > + if (mret == IRQ_HANDLED)
> > + ret = IRQ_HANDLED;
> >
>
> Not sure why you didn't like ret |= musb_interrupt(musb)...
Need to verify/clean it. I remember, was getting some issue initially
On this path.
>
> > + if (ret != IRQ_HANDLED) {
> > + if (epintr || usbintr)
> > + /*
> > + * We sometimes get unhandled IRQs in the peripheral
> > + * mode from EP0 and SOF...
> > + */
> > + DBG(2, "Unhandled USB IRQ %08x-%08x\n",
> > + epintr, usbintr);
> >
>
> This check shouldn't be needed any more -- EP0 spurious interrupts
> have been all chased down...
Ok fine.
>
> > + else if (printk_ratelimit())
> > + /*
> > + * We've seen series of spurious interrupts in the
> > + * peripheral mode after USB reset and then after some
> > + * time a real interrupt storm starting...
> > + */
> > + DBG(2, "Spurious IRQ\n");
> >
>
> Those turned out to be interrupts caused by CPPI 4.1 descriptor
> starvation (for which the controller didn't even have an interrupt bit).
> I still haven't dealt with them...
and.. AM3517 has got a bit to disable them, anyways this patch currently
supports PIO only so this check can be removed also.
>
> > + }
> > + return ret;
> > +}
> > +
> > +int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
> > +{
> > + WARNING("FIXME: %s not implemented\n", __func__);
> > + return -EIO;
> >
>
> Could be implemented using CONF2_OTGMODE...
Ok fine.
>
> > +int __init musb_platform_init(struct musb *musb)
> > +{
> > + void __iomem *reg_base = musb->ctrl_base;
> > + struct clk *otg_fck;
> > + u32 rev, lvl_intr, sw_reset;
> > +
> > + usb_nop_xceiv_register();
> > +
> > + musb->xceiv = otg_get_transceiver();
> > + if (!musb->xceiv)
> > + return -ENODEV;
> > +
> > + /* Mentor is at offset of 0x400 in AM3517 */
> > + musb->mregs += USB_MENTOR_CORE_OFFSET;
> > +
> > + /* musb->clock is already set from board/arch files */
> > + if (IS_ERR(musb->clock))
> > + return PTR_ERR(musb->clock);
> >
>
> This is checked by musb_core.c now, no need to duplicate...
Ok fine.
>
> > + if (musb->set_clock)
> > + musb->set_clock(musb->clock, 1);
> >
>
> musb->set_clock() is about to be dropped...
So there is 'else' part.
>
> > + else
> > + clk_enable(musb->clock);
> > +
> > + DBG(2, "usbotg_ck=%lud\n", clk_get_rate(musb->clock));
> >
>
> I'd put an empty line after that DBG() rather than before.
Ok fine.
>
> > + otg_fck = clk_get(musb->controller, "fck");
> > + clk_enable(otg_fck);
> >
>
> Oh, it needs two clocks... Another argument against Felipe dropping
> plat->clock. :-)
..
>
> > +
> > + DBG(2, "usbotg_phy_ck=%lud\n", clk_get_rate(otg_fck));
> >
>
> Same about empty line here...
>
> > + am3517_source_power(musb, 0, 1);
> >
>
> Effective NOP...
So need to remove.
>
> > + /* Start the on-chip PHY and its PLL. */
> > + phy_on();
> > +
> > + msleep(15);
> >
>
> 5 ms is not enough?
Need to test and correct.
>
> > + musb->a_wait_bcon = A_WAIT_BCON_TIMEOUT;
> >
>
> Hm... that line kept causing a stream of kernel messages for me,
> until I removed it. Doesn't it for you?
No I didn't get any error messages.. what messages were you getting ?
>
> > diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
> > index 98fd5b6..f8efe00 100644
> > --- a/drivers/usb/musb/musb_core.c
> > +++ b/drivers/usb/musb/musb_core.c
> > @@ -982,7 +982,8 @@ static void musb_shutdown(struct platform_device
> *pdev)
> > * more than selecting one of a bunch of predefined configurations.
> > */
> > #if defined(CONFIG_USB_TUSB6010) || \
> > - defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3)
> > + defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
> > + defined(CONFIG_MACH_OMAP3517EVM)
> >
>
> Isn't that dependency already covered by CONFIG_ARCH_OMAP3? Or else I
> don't see you adding your #ifdef around musb_platfrom_try_idle()
> declaration...
Right..this can be removed.
> +int musb_platform_exit(struct musb *musb) {
>
[...]
> + phy_off();
> +
> + usb_nop_xceiv_unregister();
> +
> + return 0;
>
>> You forgot the calls to clk_disable() for both your clocks...
Ok fine..need to correct.
Thanks,
Ajay
>
> WBR, Sergei
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] musb: add musb support for AM35x
2010-03-15 5:10 ` Gupta, Ajay Kumar
@ 2010-03-26 19:29 ` Sergei Shtylyov
0 siblings, 0 replies; 6+ messages in thread
From: Sergei Shtylyov @ 2010-03-26 19:29 UTC (permalink / raw)
To: Gupta, Ajay Kumar
Cc: linux-usb@vger.kernel.org, linux-omap@vger.kernel.org,
Felipe Balbi
Gupta, Ajay Kumar wrote:
>>> AM35x has musb interface and uses CPPI4.1 DMA engine.
>>> Current patch supports only PIO mode and there are on-going
>>> discussions on location of CPPI4.1 DMA.
>>>
>>> Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
>>> tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
>>> @@ -140,7 +140,7 @@ config USB_MUSB_HDRC_HCD
>>> config MUSB_PIO_ONLY
>>> bool 'Disable DMA (always use PIO)'
>>> depends on USB_MUSB_HDRC
>>> - default y if USB_TUSB6010
>>> + default USB_TUSB6010 || MACH_OMAP3517EVM
>>> help
>>> All data is copied between memory and FIFO by the CPU.
>>> DMA controllers are ignored.
>>> diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
>>> index 85710cc..9263033 100644
>>> --- a/drivers/usb/musb/Makefile
>>> +++ b/drivers/usb/musb/Makefile
>>> @@ -19,7 +19,11 @@ ifeq ($(CONFIG_ARCH_OMAP2430),y)
>>> endif
>>>
>>> ifeq ($(CONFIG_ARCH_OMAP3430),y)
>>> + ifeq ($(CONFIG_MACH_OMAP3517EVM),y)
>>> + musb_hdrc-objs += am3517.o
>>>
>>>
>> Isn't there some ARCH-level option for AM3517 SoC? Depending on the
>> board type doesn't really scale well...
>>
>
> AM3517 is actually based on OMAP3 but musb is different. Unfortunately there
> is no seperate *_ARCH_* defines for AM3517 alone.
>
I would really consider adding such... in the current situation the
thing won't scale with addition of some new AM35x boards.
>>> +static inline void phy_on(void)
>>> +{
>>> + u32 devconf2;
>>> +
>>> + /*
>>> + * Start the on-chip PHY and its PLL.
>>> + */
>>> + devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
>>> +
>>> + devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN |
>>> + CONF2_OTGMODE | CONF2_REFFREQ | CONF2_PHY_GPIOMODE);
>>>
>>>
>> Shouldn't you manipulate CONF2_OTGMODE in the board code instead? I
>> suspect value of 0 doesn't fit the host-only configuration (without
>> cable connected, MUSB will think it's a B-device, and the driver will
>> fail to initialize IIRC).
>>
It will fail to power the port to be precise, so that when you
finally connect a device, it won't get detected. Note that the comments
in musb_core.c twice say that the driver expects ID pin to be *forcibly
grounded* for the host-only mode while CONF2_OTGMODE's value of 0 will
leave it floating.
> I didn't see any issue in Host/Device only and OTG mode configurations
> On AM3517? Did you see any issue on DA8xx?
>
Certainly still seeing it with OTGMODE=0 setting in the host mode --
see above.
>>> +/**
>>> + * musb_platform_enable - enable interrupts
>>> + */
>>> +void musb_platform_enable(struct musb *musb)
>>> +{
>>> + void __iomem *reg_base = musb->ctrl_base;
>>> + u32 epmask, coremask;
>>> +
>>> + /* Workaround: setup IRQs through both register sets. */
>>> + epmask = ((musb->epmask & AM3517_TX_EP_MASK) << USB_INTR_TX_SHIFT) |
>>> + ((musb->epmask & AM3517_RX_EP_MASK) << USB_INTR_RX_SHIFT);
>>> + coremask = (0x01ff << USB_INTR_USB_SHIFT);
>>> +
>>> + musb_writel(reg_base, EP_INTR_MASK_SET_REG, epmask);
>>> + musb_writel(reg_base, CORE_INTR_MASK_SET_REG, coremask);
>>>
>>>
>> Hm, and I thought all CPPI 4.1 based controllers have the same
>> register layout... alas, I was wrong.
>>
>
> There are changes as AM3517 supports 15Rx/Tx endpoints.
>
Yeah, I need to accomodate cppi41_dma.c to the changes by
externalizing the code accessing the acceleration registers...
>>> + case OTG_STATE_A_WAIT_VFALL:
>>> + /*
>>> + * Wait till VBUS falls below SessionEnd (~0.2 V); the 1.3
>>> + * RTL seems to mis-handle session "start" otherwise (or in
>>> + * our case "recover"), in routine "VBUS was valid by the time
>>> + * VBUSERR got reported during enumeration" cases.
>>> + */
>>>
>>>
>> I wonder if all this still true for RTL 1.8 on which DA8xx (and
>> probably AM3517) MUSB is based...
>>
>
> Need to check on this..though I didn't see any issue in my testing.
>
There should be no issues AFAIU, just the code can be made shorter I
guess...
>>> +void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
>>> +{
>>>
>>>
>> I wonder how DaVinci gets about without musb_platfrom_try_idle()...
>>
>
> Hmm..
>
davinci.c should also define musb_platfrom_try_idle() AFAIU... it
should be no different from DA8xx in this respect.
>>> + if (ret != IRQ_HANDLED) {
>>> + if (epintr || usbintr)
>>> + /*
>>> + * We sometimes get unhandled IRQs in the peripheral
>>> + * mode from EP0 and SOF...
>>> + */
>>> + DBG(2, "Unhandled USB IRQ %08x-%08x\n",
>>> + epintr, usbintr);
>>>
>>>
>> This check shouldn't be needed any more -- EP0 spurious interrupts
>> have been all chased down...
>>
>
> Ok fine.
>
However, I seem to have found a new case of unhandled interrupts
today: when I disconnect a device, all I get is this message:
da8xx_interrupt 405: Unhandled USB IRQ 00280000
The driver failed to sense the disconnect, it's only reported when I
re-inserted a device... that's something new. Felipe, are you reading this?
>>> + musb->a_wait_bcon = A_WAIT_BCON_TIMEOUT;
>>>
>>>
>> Hm... that line kept causing a stream of kernel messages for me,
>> until I removed it. Doesn't it for you?
>>
>
> No I didn't get any error messages.. what messages were you getting ?
>
Cannot reproduce them anymore and don't remember which message it was
-- perhaps this:
musb_bus_suspend 2221: trying to suspend as a_wait_vrise is_active=1
Then it probably got fixed by:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=89368d3d11a5b2eff83ad8e752be67f77a372bad
Look at the below commit however -- it removed such code from omap2430.c:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=f7f9d63eac12b345d6243d1d608b7944a05be921
>> +int musb_platform_exit(struct musb *musb) {
>>
> [...]
>
>> + phy_off();
>> +
>> + usb_nop_xceiv_unregister();
>> +
>> + return 0;
>>
>>> You forgot the calls to clk_disable() for both your clocks...
>>>
... and clk_put() call for the functional clock.
> Ok fine..need to correct.
>
> Thanks,
> Ajay
WBR, Sergei
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2010-03-26 19:29 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-02-24 13:18 [PATCH 1/2] musb: add musb support for AM35x Ajay Kumar Gupta
[not found] ` <1267017527-17591-1-git-send-email-ajay.gupta-l0cyMroinI0@public.gmane.org>
2010-02-24 13:18 ` [PATCH 2/2] AM35x: musb: Workaround for fifo read issue Ajay Kumar Gupta
2010-03-12 14:56 ` [PATCH 1/2] musb: add musb support for AM35x Sergei Shtylyov
[not found] ` <4B9A560B.7010908-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
2010-03-15 5:10 ` Gupta, Ajay Kumar
2010-03-26 19:29 ` Sergei Shtylyov
2010-03-12 15:04 ` Sergei Shtylyov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox