* [PATCH 1/3 v3] AM35x: Add musb support
@ 2010-05-17 10:47 Ajay Kumar Gupta
[not found] ` <1274093235-7616-1-git-send-email-ajay.gupta-l0cyMroinI0@public.gmane.org>
0 siblings, 1 reply; 6+ messages in thread
From: Ajay Kumar Gupta @ 2010-05-17 10:47 UTC (permalink / raw)
To: linux-usb-u79uwXL29TY76Z2rM5mHXA
Cc: linux-omap-u79uwXL29TY76Z2rM5mHXA,
felipe.balbi-xNZwKgViW5gAvxtiuMwx3w, Ajay Kumar Gupta
AM35x has musb interface (version 1.8) and uses CPPI41 DMA engine.
It supports upto 500mA of power in host mode.
Signed-off-by: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org>
---
Patch created against linus'tree + all musb patches in Greg's queue
and patches available in linux-omap/for-next branch.
arch/arm/mach-omap2/board-am3517evm.c | 43 +++++++++++++++++++++++++++++++++
arch/arm/mach-omap2/usb-musb.c | 4 +++
arch/arm/plat-omap/include/plat/usb.h | 21 ++++++++++++++++
3 files changed, 68 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index af383a8..313559c 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -35,6 +35,7 @@
#include <plat/control.h>
#include <plat/usb.h>
#include <plat/display.h>
+#include <plat/control.h>
#include "mux.h"
@@ -375,6 +376,43 @@ static void __init am3517_evm_init_irq(void)
omap_gpio_init();
}
+static struct omap_musb_board_data musb_board_data = {
+ .interface_type = MUSB_INTERFACE_ULPI,
+ .mode = MUSB_OTG,
+ .power = 500,
+};
+
+static __init void am3517_evm_musb_init(void)
+{
+ u32 devconf2;
+
+ /*
+ * Set up USB clock/mode in the DEVCONF2 register.
+ */
+ devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+
+ /* USB2.0 PHY reference clock is 13 MHz */
+ devconf2 &= ~CONF2_REFFREQ;
+ devconf2 |= CONF2_REFFREQ_13MHZ;
+
+ /*
+ * We have to override VBUS/ID signals when MUSB is configured into the
+ * host-only mode -- ID pin will float if no cable is connected, so the
+ * controller won't be able to drive VBUS thinking that it's a B-device.
+ * Otherwise, we want to use the OTG mode and enable VBUS comparators.
+ */
+ devconf2 &= ~CONF2_OTGMODE;
+#ifdef CONFIG_USB_MUSB_HOST
+ devconf2 |= CONF2_FORCE_HOST;
+#else
+ devconf2 |= CONF2_SESENDEN | CONF2_VBDTCTEN;
+#endif
+
+ omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+
+ usb_musb_init(&musb_board_data);
+}
+
static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
#if defined(CONFIG_PANEL_SHARP_LQ043T1DG01) || \
@@ -393,6 +431,8 @@ static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
#ifdef CONFIG_OMAP_MUX
static struct omap_board_mux board_mux[] __initdata = {
+ /* USB OTG DRVVBUS offset = 0x212 */
+ OMAP3_MUX(SAD2D_MCAD23, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
{ .reg_offset = OMAP_MUX_TERMINATOR },
};
#else
@@ -459,6 +499,9 @@ static void __init am3517_evm_init(void)
ARRAY_SIZE(am3517evm_i2c1_boardinfo));
/*Ethernet*/
am3517_evm_ethernet_init(&am3517_evm_emac_pdata);
+
+ /* MUSB */
+ am3517_evm_musb_init();
}
static void __init am3517_evm_map_io(void)
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index 3befddb..883795b 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -21,6 +21,7 @@
#include <linux/usb/musb.h>
#include <mach/irqs.h>
+#include <mach/am35xx.h>
#include <plat/usb.h>
#ifdef CONFIG_USB_MUSB_SOC
@@ -69,6 +70,9 @@ void __init usb_musb_init(struct omap_musb_board_data *board_data)
{
if (cpu_is_omap243x()) {
musb_resources[0].start = OMAP243X_HS_BASE;
+ } else if (cpu_is_omap3517()) {
+ musb_resources[0].start = AM35XX_IPSS_USBOTGSS_BASE;
+ musb_resources[1].start = INT_35XX_USBOTG_IRQ;
} else if (cpu_is_omap34xx()) {
musb_resources[0].start = OMAP34XX_HSUSB_OTG_BASE;
} else if (cpu_is_omap44xx()) {
diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h
index 60c734f..c7a019c 100644
--- a/arch/arm/plat-omap/include/plat/usb.h
+++ b/arch/arm/plat-omap/include/plat/usb.h
@@ -168,5 +168,26 @@ void omap_usb_init(struct omap_usb_config *pdata);
# define USBT2TLL5PI (1 << 17)
# define USB0PUENACTLOI (1 << 16)
# define USBSTANDBYCTRL (1 << 15)
+/* AM3517 */
+/* USB 2.0 PHY Control */
+#define CONF2_PHY_GPIOMODE (1 << 23)
+#define CONF2_OTGMODE (3 << 14)
+#define CONF2_NO_OVERRIDE (0 << 14)
+#define CONF2_FORCE_HOST (1 << 14)
+#define CONF2_FORCE_DEVICE (2 << 14)
+#define CONF2_FORCE_HOST_VBUS_LOW (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)
#endif /* __ASM_ARCH_OMAP_USB_H */
--
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
* [PATCH 2/3 v3] musb: add musb support for AM35x
[not found] ` <1274093235-7616-1-git-send-email-ajay.gupta-l0cyMroinI0@public.gmane.org>
@ 2010-05-17 10:47 ` Ajay Kumar Gupta
2010-05-17 10:47 ` [PATCH 3/3] musb: AM35x: Workaround for fifo read issue Ajay Kumar Gupta
0 siblings, 1 reply; 6+ messages in thread
From: Ajay Kumar Gupta @ 2010-05-17 10:47 UTC (permalink / raw)
To: linux-usb-u79uwXL29TY76Z2rM5mHXA
Cc: linux-omap-u79uwXL29TY76Z2rM5mHXA,
felipe.balbi-xNZwKgViW5gAvxtiuMwx3w, 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-l0cyMroinI0@public.gmane.org>
---
Patch created against linus'tree + all musb patches in Greg's queue
Changes from v2:
- fixed multipline comment style
- Removed unneeded 'coremask' variable
- Added 'break' instead of 'return'
- Updated musb_platform_init signature
I had to use MACH_OMAP3517EVM as there is no ARCH_xxx config specific to
AM3517 platforms other than ARCH_OMAP3.
drivers/usb/musb/Kconfig | 4 +-
drivers/usb/musb/Makefile | 4 +
drivers/usb/musb/am3517.c | 517 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 523 insertions(+), 2 deletions(-)
create mode 100644 drivers/usb/musb/am3517.c
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 7fab721..68efecf 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, ...)'
@@ -144,7 +144,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 9705f71..ce57675 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_ARCH_OMAP4),y)
diff --git a/drivers/usb/musb/am3517.c b/drivers/usb/musb/am3517.c
new file mode 100644
index 0000000..b74e664
--- /dev/null
+++ b/drivers/usb/musb/am3517.c
@@ -0,0 +1,517 @@
+/*
+ * 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-Igf4POYTYCDQT0dZR+AlfA@public.gmane.org>
+ *
+ * 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
+ */
+/* USB 2.0 OTG module registers */
+#define USB_REVISION_REG 0x00
+#define USB_CTRL_REG 0x04
+#define USB_STAT_REG 0x08
+#define USB_EMULATION_REG 0x0c
+/* 0x10 Reserved */
+#define USB_AUTOREQ_REG 0x14
+#define USB_SRP_FIX_TIME_REG 0x18
+#define USB_TEARDOWN_REG 0x1c
+#define EP_INTR_SRC_REG 0x20
+#define EP_INTR_SRC_SET_REG 0x24
+#define EP_INTR_SRC_CLEAR_REG 0x28
+#define EP_INTR_MASK_REG 0x2c
+#define EP_INTR_MASK_SET_REG 0x30
+#define EP_INTR_MASK_CLEAR_REG 0x34
+#define EP_INTR_SRC_MASKED_REG 0x38
+#define CORE_INTR_SRC_REG 0x40
+#define CORE_INTR_SRC_SET_REG 0x44
+#define CORE_INTR_SRC_CLEAR_REG 0x48
+#define CORE_INTR_MASK_REG 0x4c
+#define CORE_INTR_MASK_SET_REG 0x50
+#define CORE_INTR_MASK_CLEAR_REG 0x54
+#define CORE_INTR_SRC_MASKED_REG 0x58
+/* 0x5c Reserved */
+#define USB_END_OF_INTR_REG 0x60
+
+/* Control register bits */
+#define USB_SOFT_RESET_MASK 1
+
+/* USB interrupt register bits */
+#define USB_INTR_USB_SHIFT 16
+#define USB_INTR_USB_MASK (0x1ff << USB_INTR_USB_SHIFT)
+#define USB_INTR_DRVVBUS 0x100
+#define USB_INTR_RX_SHIFT 16
+#define USB_INTR_TX_SHIFT 0
+#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 USB_MENTOR_CORE_OFFSET 0x400
+
+static inline void phy_on(void)
+{
+ unsigned long timeout = jiffies + msecs_to_jiffies(100);
+ 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_PHY_GPIOMODE);
+ devconf2 |= CONF2_PHY_PLLON | 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();
+
+ if (time_after(jiffies, timeout)) {
+ DBG(1, "musb PHY clock good timed out\n");
+ break;
+ }
+ }
+}
+
+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;
+
+ /* 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);
+
+ musb_writel(reg_base, EP_INTR_MASK_SET_REG, epmask);
+ musb_writel(reg_base, CORE_INTR_MASK_SET_REG, USB_INTR_USB_MASK);
+
+ /* 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);
+}
+
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+#define portstate(stmt) stmt
+#else
+#define portstate(stmt)
+#endif
+
+static void am3517_set_vbus(struct musb *musb, int is_on)
+{
+ WARN_ON(is_on && is_peripheral_active(musb));
+}
+
+#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:
+ 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;
+
+ 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. */
+ 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)
+ ret |= musb_interrupt(musb);
+
+ 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);
+
+ return ret;
+}
+
+int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
+{
+ u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+
+ devconf2 &= ~CONF2_OTGMODE;
+ switch (musb_mode) {
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+ case MUSB_HOST: /* Force VBUS valid, ID = 0 */
+ devconf2 |= CONF2_FORCE_HOST;
+ break;
+#endif
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+ case MUSB_PERIPHERAL: /* Force VBUS valid, ID = 1 */
+ devconf2 |= CONF2_FORCE_DEVICE;
+ break;
+#endif
+#ifdef CONFIG_USB_MUSB_OTG
+ case MUSB_OTG: /* Don't override the VBUS/ID comparators */
+ devconf2 |= CONF2_NO_OVERRIDE;
+ break;
+#endif
+ default:
+ DBG(2, "Trying to set unsupported mode %u\n", musb_mode);
+ }
+
+ omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+ return 0;
+}
+
+int __init musb_platform_init(struct musb *musb, void *board_data)
+{
+ void __iomem *reg_base = musb->ctrl_base;
+ struct clk *otg_fck;
+ u32 rev, lvl_intr, sw_reset;
+
+ musb->mregs += USB_MENTOR_CORE_OFFSET;
+
+ 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;
+
+ usb_nop_xceiv_register();
+ musb->xceiv = otg_get_transceiver();
+ if (!musb->xceiv)
+ return -ENODEV;
+
+ if (is_host_enabled(musb))
+ setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);
+
+ musb->board_set_vbus = am3517_set_vbus;
+
+ /* 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(5);
+
+ 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)
+{
+ struct clk *otg_fck = clk_get(musb->controller, "fck");
+
+ if (is_host_enabled(musb))
+ del_timer_sync(&otg_workaround);
+
+ /* Delay to avoid problems with module reload... */
+ if (is_host_enabled(musb) && musb->xceiv->default_a) {
+ u8 devctl, warn = 0;
+ int delay;
+
+ /*
+ * If there's no peripheral connected, VBUS can take a
+ * long time to fall...
+ */
+ for (delay = 30; delay > 0; delay--) {
+ devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+ if (!(devctl & MUSB_DEVCTL_VBUS))
+ goto done;
+ if ((devctl & MUSB_DEVCTL_VBUS) != warn) {
+ warn = devctl & MUSB_DEVCTL_VBUS;
+ DBG(1, "VBUS %d\n",
+ warn >> MUSB_DEVCTL_VBUS_SHIFT);
+ }
+ msleep(1000);
+ }
+
+ /* In OTG mode, another host might be connected... */
+ DBG(1, "VBUS off timeout (devctl %02x)\n", devctl);
+ }
+done:
+ phy_off();
+
+ usb_nop_xceiv_unregister();
+
+ if (musb->set_clock)
+ musb->set_clock(musb->clock, 0);
+ else
+ clk_disable(musb->clock);
+
+ if (otg_fck) {
+ clk_put(otg_fck);
+ clk_disable(otg_fck);
+ }
+
+ 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
--
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
* [PATCH 3/3] musb: AM35x: Workaround for fifo read issue
2010-05-17 10:47 ` [PATCH 2/3 v3] musb: add musb support for AM35x Ajay Kumar Gupta
@ 2010-05-17 10:47 ` Ajay Kumar Gupta
2010-05-18 9:59 ` Sergei Shtylyov
0 siblings, 1 reply; 6+ messages in thread
From: Ajay Kumar Gupta @ 2010-05-17 10:47 UTC (permalink / raw)
To: linux-usb; +Cc: linux-omap, felipe.balbi, 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@ti.com>
---
Patch created against linus'tree + all musb patches in Greg's queue
Changes from v2:
- fixed multipline comment style
drivers/usb/musb/am3517.c | 31 +++++++++++++++++++++++++++++++
drivers/usb/musb/musb_core.c | 2 ++
2 files changed, 33 insertions(+), 0 deletions(-)
diff --git a/drivers/usb/musb/am3517.c b/drivers/usb/musb/am3517.c
index b74e664..c68c784 100644
--- a/drivers/usb/musb/am3517.c
+++ b/drivers/usb/musb/am3517.c
@@ -515,3 +515,34 @@ 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 4093f6d..9c59a8e 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -262,6 +262,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
*/
@@ -299,6 +300,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
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 3/3] musb: AM35x: Workaround for fifo read issue
2010-05-17 10:47 ` [PATCH 3/3] musb: AM35x: Workaround for fifo read issue Ajay Kumar Gupta
@ 2010-05-18 9:59 ` Sergei Shtylyov
[not found] ` <4BF26511.2060705-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
0 siblings, 1 reply; 6+ messages in thread
From: Sergei Shtylyov @ 2010-05-18 9:59 UTC (permalink / raw)
To: Ajay Kumar Gupta; +Cc: linux-usb, linux-omap, felipe.balbi
Hello.
Ajay Kumar Gupta wrote:
> 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@ti.com>
> ---
> Patch created against linus'tree + all musb patches in Greg's queue
> Changes from v2:
> - fixed multipline comment style
> drivers/usb/musb/am3517.c | 31 +++++++++++++++++++++++++++++++
> drivers/usb/musb/musb_core.c | 2 ++
> 2 files changed, 33 insertions(+), 0 deletions(-)
> diff --git a/drivers/usb/musb/am3517.c b/drivers/usb/musb/am3517.c
> index b74e664..c68c784 100644
> --- a/drivers/usb/musb/am3517.c
> +++ b/drivers/usb/musb/am3517.c
> @@ -515,3 +515,34 @@ 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) {
You don't need to put likely() in parens.
> + readsl(fifo, dst, len >> 2);
> + dst += (len & ~0x03);
You don't need parens here as well.
> + 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);
Can't you do away with memcpy() here?
> + dst += 4;
> + }
> + len %= 4;
> + }
> + if (len > 0) {
> + val = musb_readl(fifo, 0);
> + memcpy(dst, &val, len);
> + }
> +}
WBR, Sergei
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [PATCH 3/3] musb: AM35x: Workaround for fifo read issue
[not found] ` <4BF26511.2060705-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
@ 2010-05-18 10:11 ` Gupta, Ajay Kumar
2010-05-18 10:26 ` Gupta, Ajay Kumar
0 siblings, 1 reply; 6+ messages in thread
From: Gupta, Ajay Kumar @ 2010-05-18 10:11 UTC (permalink / raw)
To: Sergei Shtylyov
Cc: linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-omap-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
felipe.balbi-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org
Hi,
> Ajay Kumar Gupta wrote:
>
> > 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>
> > ---
> > Patch created against linus'tree + all musb patches in Greg's queue
> > Changes from v2:
> > - fixed multipline comment style
> > drivers/usb/musb/am3517.c | 31 +++++++++++++++++++++++++++++++
> > drivers/usb/musb/musb_core.c | 2 ++
> > 2 files changed, 33 insertions(+), 0 deletions(-)
>
> > diff --git a/drivers/usb/musb/am3517.c b/drivers/usb/musb/am3517.c
> > index b74e664..c68c784 100644
> > --- a/drivers/usb/musb/am3517.c
> > +++ b/drivers/usb/musb/am3517.c
> > @@ -515,3 +515,34 @@ 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) {
>
> You don't need to put likely() in parens.
Ok.
>
> > + readsl(fifo, dst, len >> 2);
> > + dst += (len & ~0x03);
>
> You don't need parens here as well.
Ok.
>
> > + 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);
>
> Can't you do away with memcpy() here?
Are you asking for change below?
*(u32 *)dst = musb_readl(fifo, 0);
-Ajay
>
> > + dst += 4;
> > + }
> > + len %= 4;
> > + }
> > + if (len > 0) {
> > + val = musb_readl(fifo, 0);
> > + memcpy(dst, &val, len);
> > + }
> > +}
>
> 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 3/3] musb: AM35x: Workaround for fifo read issue
2010-05-18 10:11 ` Gupta, Ajay Kumar
@ 2010-05-18 10:26 ` Gupta, Ajay Kumar
0 siblings, 0 replies; 6+ messages in thread
From: Gupta, Ajay Kumar @ 2010-05-18 10:26 UTC (permalink / raw)
To: Gupta, Ajay Kumar, Sergei Shtylyov
Cc: linux-usb@vger.kernel.org, linux-omap@vger.kernel.org,
felipe.balbi@nokia.com
Hi,
> > Ajay Kumar Gupta wrote:
> >
> > > 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@ti.com>
> > > ---
> > > Patch created against linus'tree + all musb patches in Greg's queue
> > > Changes from v2:
> > > - fixed multipline comment style
> > > drivers/usb/musb/am3517.c | 31 +++++++++++++++++++++++++++++++
> > > drivers/usb/musb/musb_core.c | 2 ++
> > > 2 files changed, 33 insertions(+), 0 deletions(-)
> >
> > > diff --git a/drivers/usb/musb/am3517.c b/drivers/usb/musb/am3517.c
> > > index b74e664..c68c784 100644
> > > --- a/drivers/usb/musb/am3517.c
> > > +++ b/drivers/usb/musb/am3517.c
> > > @@ -515,3 +515,34 @@ 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) {
> >
> > You don't need to put likely() in parens.
>
> Ok.
>
> >
> > > + readsl(fifo, dst, len >> 2);
> > > + dst += (len & ~0x03);
> >
> > You don't need parens here as well.
>
> Ok.
>
> >
> > > + 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);
> >
> > Can't you do away with memcpy() here?
> Are you asking for change below?
> *(u32 *)dst = musb_readl(fifo, 0);
This one is safe and works but the other memcpy (below one) would
not be safe to replace as the length would be 1 to 3 bytes.
-Ajay
> > > + dst += 4;
> > > + }
> > > + len %= 4;
> > > + }
> > > + if (len > 0) {
> > > + val = musb_readl(fifo, 0);
> > > + memcpy(dst, &val, len);
> > > + }
> > > +}
> >
> > WBR, Sergei
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2010-05-18 10:26 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-05-17 10:47 [PATCH 1/3 v3] AM35x: Add musb support Ajay Kumar Gupta
[not found] ` <1274093235-7616-1-git-send-email-ajay.gupta-l0cyMroinI0@public.gmane.org>
2010-05-17 10:47 ` [PATCH 2/3 v3] musb: add musb support for AM35x Ajay Kumar Gupta
2010-05-17 10:47 ` [PATCH 3/3] musb: AM35x: Workaround for fifo read issue Ajay Kumar Gupta
2010-05-18 9:59 ` Sergei Shtylyov
[not found] ` <4BF26511.2060705-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
2010-05-18 10:11 ` Gupta, Ajay Kumar
2010-05-18 10:26 ` Gupta, Ajay Kumar
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).