Commit 6c2e4b39 authored by David Brownell's avatar David Brownell Committed by Tony Lindgren

MUSB: Add initial MUSB and TUSB support

This patch adds support for MUSB and TUSB controllers
integrated into omap2430 and davinci. It also adds support
for external tusb6010 controller.

This patch still needs clean-up work before it will be
submitted to the mainline kernel.

For more information, please see:

http://sourceforge.net/mailarchive/forum.php?thread_id=30389954&forum_id=5398
parent b121da1e
......@@ -53,6 +53,7 @@ obj-$(CONFIG_ATA_OVER_ETH) += block/aoe/
obj-$(CONFIG_PARIDE) += block/paride/
obj-$(CONFIG_TC) += tc/
obj-$(CONFIG_USB) += usb/
obj-$(CONFIG_USB_MUSB_HDRC) += usb/musb/
obj-$(CONFIG_PCI) += usb/
obj-$(CONFIG_USB_GADGET) += usb/gadget/
obj-$(CONFIG_GAMEPORT) += input/gameport/
......
......@@ -80,6 +80,8 @@ source "drivers/usb/core/Kconfig"
source "drivers/usb/host/Kconfig"
source "drivers/usb/musb/Kconfig"
source "drivers/usb/class/Kconfig"
source "drivers/usb/storage/Kconfig"
......
......@@ -155,6 +155,16 @@ config USB_LH7A40X
select USB_GADGET_SELECTED
# built in ../musb along with host support
config USB_GADGET_MUSB_HDRC
boolean "Inventra HDRC USB Peripheral (TI, ...)"
depends on USB_MUSB_HDRC && (USB_MUSB_PERIPHERAL || USB_MUSB_OTG)
select USB_GADGET_DUALSPEED
select USB_GADGET_SELECTED
help
This OTG-capable silicon IP is used in dual designs including
the TI DaVinci, OMAP 243x, OMAP 343x, and TUSB 6010.
config USB_GADGET_OMAP
boolean "OMAP USB Device Controller"
depends on ARCH_OMAP1
......
#
# USB Dual Role (OTG-ready) Controller Drivers
# for silicon based on Mentor Graphics INVENTRA designs
#
comment "Enable Host or Gadget support to see Inventra options"
depends on !USB && USB_GADGET=n
# (M)HDRC = (Multipoint) Highspeed Dual-Role Controller
config USB_MUSB_HDRC
depends on USB || USB_GADGET
tristate 'Inventra Highspeed Dual Role Controller (TI, ...)'
help
Say Y here if your system has a dual role high speed USB
controller based on the Mentor Graphics silicon IP. Then
configure options to match your silicon and the board
it's being used with, including the USB peripheral role,
or the USB host role, or both.
Texas Instruments parts using this IP include DaVinci 644x,
OMAP 243x, OMAP 343x, and TUSB 6010.
If you do not know what this is, please say N.
To compile this driver as a module, choose M here; the
module will be called "musb_hdrc".
config USB_MUSB_SOC
boolean
depends on USB_MUSB_HDRC
default y if ARCH_DAVINCI
default y if ARCH_OMAP243X
default y if ARCH_OMAP343X
help
Use a static <asm/arch/hdrc_cnf.h> file to describe how the
controller is configured (endpoints, mechanisms, etc) on the
current iteration of a given system-on-chip.
comment "DaVinci 644x USB support"
depends on USB_MUSB_HDRC && ARCH_DAVINCI
comment "OMAP 243x high speed USB support"
depends on USB_MUSB_HDRC && ARCH_OMAP243X
comment "OMAP 343x high speed USB support"
depends on USB_MUSB_HDRC && ARCH_OMAP343X
config USB_TUSB6010
boolean "TUSB 6010 support"
depends on USB_MUSB_HDRC && !USB_MUSB_SOC
default y
help
The TUSB 6010 chip, from Texas Instruments, connects a discrete
HDRC core using a 16-bit parallel bus (NOR flash style) or VLYNQ
(a high speed serial link). It can use system-specific external
DMA controllers.
choice
prompt "Driver Mode"
depends on USB_MUSB_HDRC
help
Dual-Role devices can support both host and peripheral roles,
as well as a the special "OTG Device" role which can switch
between both roles as needed.
# use USB_MUSB_HDRC_HCD not USB_MUSB_HOST to #ifdef host side support;
# OTG needs both roles, not just USB_MUSB_HOST.
config USB_MUSB_HOST
depends on USB
bool "USB Host"
help
Say Y here if your system supports the USB host role.
If it has a USB "A" (rectangular), "Mini-A" (uncommon),
or "Mini-AB" connector, it supports the host role.
(With a "Mini-AB" connector, you should enable USB OTG.)
# use USB_GADGET_MUSB_HDRC not USB_MUSB_PERIPHERAL to #ifdef peripheral
# side support ... OTG needs both roles
config USB_MUSB_PERIPHERAL
depends on USB_GADGET
bool "USB Peripheral (gadget stack)"
select USB_GADGET_MUSB_HDRC
help
Say Y here if your system supports the USB peripheral role.
If it has a USB "B" (squarish), "Mini-B", or "Mini-AB"
connector, it supports the peripheral role.
(With a "Mini-AB" connector, you should enable USB OTG.)
config USB_MUSB_OTG
depends on USB && USB_GADGET && EXPERIMENTAL
bool "Both host and peripheral: USB OTG (On The Go) Device"
select USB_GADGET_MUSB_HDRC
select USB_OTG
select PM
help
The most notable feature of USB OTG is support for a
"Dual-Role" device, which can act as either a device
or a host. The initial role choice can be changed
later, when two dual-role devices talk to each other.
At this writing, the OTG support in this driver is incomplete,
omitting the mandatory HNP or SRP protocols. However, some
of the cable based role switching works. (That is, grounding
the ID pin switches the controller to host mode, while leaving
it floating leaves it in peripheral mode.)
Select this if your system has a Mini-AB connector, or
to simplify certain kinds of configuration.
To implement your OTG Targeted Peripherals List (TPL), enable
USB_OTG_WHITELIST and update "drivers/usb/core/otg_whitelist.h"
to match your requirements.
endchoice
# enable peripheral support (including with OTG)
config USB_GADGET_MUSB_HDRC
bool
depends on USB_MUSB_HDRC && (USB_MUSB_PERIPHERAL || USB_MUSB_OTG)
# default y
# select USB_GADGET_DUALSPEED
# select USB_GADGET_SELECTED
# enables host support (including with OTG)
config USB_MUSB_HDRC_HCD
bool
depends on USB_MUSB_HDRC && (USB_MUSB_HOST || USB_MUSB_OTG)
select USB_OTG if USB_GADGET_MUSB_HDRC
default y
config USB_INVENTRA_FIFO
bool 'Disable DMA (always use PIO)'
depends on USB_MUSB_HDRC
default y if USB_TUSB6010
help
All data is copied between memory and FIFO by the CPU.
DMA controllers are ignored.
Do not select 'n' here unless DMA support for your SOC or board
is unavailable (or unstable). When DMA is enabled at compile time,
you can still disable it at run time using the "use_dma=n" module
parameter.
config USB_INVENTRA_DMA
bool
depends on USB_MUSB_HDRC && !USB_INVENTRA_FIFO
default ARCH_OMAP243X || ARCH_OMAP343X
help
Enable DMA transfers using Mentor's engine.
config USB_TI_CPPI_DMA
bool
depends on USB_MUSB_HDRC && !USB_INVENTRA_FIFO
default ARCH_DAVINCI
help
Enable DMA transfers when TI CPPI DMA is available.
config USB_TUSB_OMAP_DMA
bool
depends on USB_MUSB_HDRC && !USB_INVENTRA_FIFO
depends on USB_TUSB6010
depends on ARCH_OMAP
default y
help
Enable DMA transfers on TUSB 6010 when OMAP DMA is available.
config USB_INVENTRA_HCD_LOGGING
depends on USB_MUSB_HDRC
int 'Logging Level (0 - none / 3 - annoying / ... )'
default 0
help
Set the logging level. 0 disables the debugging altogether,
although when USB_DEBUG is set the value is at least 1.
Starting at level 3, per-transfer (urb, usb_request, packet,
or dma transfer) tracing may kick in.
#
# for USB OTG silicon based on Mentor Graphics INVENTRA designs
#
musb_hdrc-objs := plat_uds.o
obj-$(CONFIG_USB_MUSB_HDRC) += musb_hdrc.o
ifeq ($(CONFIG_ARCH_DAVINCI),y)
musb_hdrc-objs += davinci.o
endif
ifeq ($(CONFIG_USB_TUSB6010),y)
musb_hdrc-objs += tusb6010.o
endif
ifeq ($(CONFIG_ARCH_OMAP243X),y)
musb_hdrc-objs += omap2430.o
endif
ifeq ($(CONFIG_USB_MUSB_OTG),y)
musb_hdrc-objs += otg.o
endif
ifeq ($(CONFIG_USB_GADGET_MUSB_HDRC),y)
musb_hdrc-objs += g_ep0.o musb_gadget.o
endif
ifeq ($(CONFIG_USB_MUSB_HDRC_HCD),y)
musb_hdrc-objs += virthub.o musb_host.o
endif
# the kconfig must guarantee that only one of the
# possible I/O schemes will be enabled at a time ...
# PIO (INVENTRA_FIFO), or DMA (several potential schemes).
# though PIO is always there to back up DMA, and for ep0
ifneq ($(CONFIG_USB_INVENTRA_FIFO),y)
ifeq ($(CONFIG_USB_INVENTRA_DMA),y)
musb_hdrc-objs += musbhsdma.o
else
ifeq ($(CONFIG_USB_TI_CPPI_DMA),y)
musb_hdrc-objs += cppi_dma.o
else
ifeq ($(CONFIG_USB_TUSB_OMAP_DMA),y)
musb_hdrc-objs += tusb6010_omap.o
endif
endif
endif
endif
################################################################################
# FIXME remove all these extra "-DMUSB_* things, stick to CONFIG_*
ifeq ($(CONFIG_USB_INVENTRA_MUSB_HAS_AHB_ID),y)
EXTRA_CFLAGS += -DMUSB_AHB_ID
endif
# Debugging
MUSB_DEBUG:=$(CONFIG_USB_INVENTRA_HCD_LOGGING)
ifeq ("$(strip $(MUSB_DEBUG))","")
ifdef CONFIG_USB_DEBUG
MUSB_DEBUG:=1
else
MUSB_DEBUG:=0
endif
endif
ifneq ($(MUSB_DEBUG),0)
EXTRA_CFLAGS += -DDEBUG
ifeq ($(CONFIG_PROC_FS),y)
musb_hdrc-objs += musb_procfs.o
endif
endif
EXTRA_CFLAGS += -DMUSB_DEBUG=$(MUSB_DEBUG)
This diff is collapsed.
/* Copyright (C) 2005-2006 by Texas Instruments */
#ifndef _CPPI_DMA_H_
#define _CPPI_DMA_H_
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/dmapool.h>
#include "dma.h"
#include "musbdefs.h"
#include "davinci.h"
/* hOptions bit masks for CPPI BDs */
#define CPPI_SOP_SET ((u32)(1 << 31))
#define CPPI_EOP_SET ((u32)(1 << 30))
#define CPPI_OWN_SET ((u32)(1 << 29)) /* owned by cppi */
#define CPPI_EOQ_MASK ((u32)(1 << 28))
#define CPPI_ZERO_SET ((u32)(1 << 23)) /* rx saw zlp; tx issues one */
#define CPPI_RXABT_MASK ((u32)(1 << 19)) /* need more rx buffers */
#define CPPI_RECV_PKTLEN_MASK 0xFFFF
#define CPPI_BUFFER_LEN_MASK 0xFFFF
#define CPPI_TEAR_READY ((u32)(1 << 31))
/* CPPI data structure definitions */
#define CPPI_DESCRIPTOR_ALIGN 16 // bytes; 5-dec docs say 4-byte align
struct cppi_descriptor {
/* Hardware Overlay */
u32 hNext; /**< Next(hardware) Buffer Descriptor Pointer */
u32 buffPtr; /**<Buffer Pointer (dma_addr_t) */
u32 bOffBLen; /**<Buffer_offset16,buffer_length16 */
u32 hOptions; /**<Option fields for SOP,EOP etc*/
struct cppi_descriptor *next;
dma_addr_t dma; /* address of this descriptor */
/* for Rx Desc, track original Buffer len to detect short packets */
u32 enqBuffLen;
} __attribute__ ((aligned(CPPI_DESCRIPTOR_ALIGN)));
/* forward declaration for CppiDmaController structure */
struct cppi;
/**
* Channel Control Structure
*
* CPPI Channel Control structure. Using he same for Tx/Rx. If need be
* derive out of this later.
*/
struct cppi_channel {
/* First field must be dma_channel for easy type casting
* FIXME just use container_of() and be typesafe instead!
*/
struct dma_channel Channel;
/* back pointer to the Dma Controller structure */
struct cppi *pController;
/* which direction of which endpoint? */
struct musb_hw_ep *pEndPt;
u8 bTransmit;
u8 chNo;
/* DMA modes: RNDIS or "transparent" */
u8 bLastModeRndis;
/* book keeping for current transfer request */
dma_addr_t startAddr;
u32 transferSize;
u32 pktSize;
u32 currOffset; /* requested segments */
u32 actualLen; /* completed (Channel.actual) */
void __iomem *stateRam; /* CPPI state */
/* BD management fields */
struct cppi_descriptor *bdPoolHead;
struct cppi_descriptor *activeQueueHead;
struct cppi_descriptor *activeQueueTail;
struct cppi_descriptor *lastHwBDProcessed;
/* use tx_complete in host role to track endpoints waiting for
* FIFONOTEMPTY to clear.
*/
struct list_head tx_complete;
};
/**
* CPPI Dma Controller Object
*
* CPPI Dma controller object.Encapsulates all bookeeping and Data
* structures pertaining to the CPPI Dma Controller.
*/
struct cppi {
struct dma_controller Controller;
struct musb *musb;
void __iomem *pCoreBase;
struct cppi_channel txCppi[MUSB_C_NUM_EPT - 1];
struct cppi_channel rxCppi[MUSB_C_NUM_EPR - 1];
struct dma_pool *pool;
struct list_head tx_complete;
};
/* irq handling hook */
extern void cppi_completion(struct musb *, u32 rx, u32 tx);
#endif /* end of ifndef _CPPI_DMA_H_ */
/*
* Copyright (C) 2005-2006 by Texas Instruments
*
* 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/config.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>
#include <asm/arch/memory.h>
// #include <asm/arch/gpio.h>
#include <asm/mach-types.h>
#include "musbdefs.h"
#ifdef CONFIG_ARCH_DAVINCI
#ifdef CONFIG_MACH_DAVINCI_EVM
#include <asm/arch/i2c-client.h>
#endif
#include "davinci.h"
#endif
#ifdef CONFIG_USB_TI_CPPI_DMA
#include "cppi_dma.h"
#endif
static inline void phy_on(void)
{
/* start the on-chip PHY and its PLL */
__raw_writel(USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON,
IO_ADDRESS(USBPHY_CTL_PADDR));
while ((__raw_readl(IO_ADDRESS(USBPHY_CTL_PADDR))
& USBPHY_PHYCLKGD) == 0)
cpu_relax();
}
static inline void phy_off(void)
{
/* powerdown the on-chip PHY and its oscillator */
__raw_writel(USBPHY_OSCPDWN | USBPHY_PHYSPDWN,
IO_ADDRESS(USBPHY_CTL_PADDR));
}
static int dma_off = 1;
void musb_platform_enable(struct musb *musb)
{
u32 tmp, old, val;
/* workaround: setup irqs through both register sets */
tmp = (musb->wEndMask & DAVINCI_USB_TX_ENDPTS_MASK)
<< DAVINCI_USB_TXINT_SHIFT;
musb_writel(musb->ctrl_base, DAVINCI_USB_INT_MASK_SET_REG, tmp);
old = tmp;
tmp = (musb->wEndMask & (0xfffe & DAVINCI_USB_RX_ENDPTS_MASK))
<< DAVINCI_USB_RXINT_SHIFT;
musb_writel(musb->ctrl_base, DAVINCI_USB_INT_MASK_SET_REG, tmp);
tmp |= old;
val = ~MGC_M_INTR_SOF;
tmp |= ((val & 0x01ff) << DAVINCI_USB_USBINT_SHIFT);
musb_writel(musb->ctrl_base, DAVINCI_USB_INT_MASK_SET_REG, tmp);
if (is_dma_capable() && !dma_off)
printk(KERN_WARNING "%s %s: dma not reactivated\n",
__FILE__, __FUNCTION__);
else
dma_off = 0;
}
/*
* Disable the HDRC and flush interrupts
*/
void musb_platform_disable(struct musb *musb)
{
/* because we don't set CTRLR.UINT, "important" to:
* - not read/write INTRUSB/INTRUSBE
* - (except during initial setup, as workaround)
* - use INTSETR/INTCLRR instead
*/
musb_writel(musb->ctrl_base, DAVINCI_USB_INT_MASK_CLR_REG,
DAVINCI_USB_USBINT_MASK
| DAVINCI_USB_TXINT_MASK
| DAVINCI_USB_RXINT_MASK);
musb_writeb(musb->pRegs, MGC_O_HDRC_DEVCTL, 0);
musb_writel(musb->ctrl_base, DAVINCI_USB_EOI_REG, 0);
if (is_dma_capable() && !dma_off)
WARN("dma still active\n");
}
/* REVISIT this file shouldn't modify the OTG state machine ...
*
* The OTG infrastructure needs updating, to include things like
* offchip DRVVBUS support and replacing MGC_OtgMachineInputs with
* musb struct members (so e.g. vbus_state vanishes).
*/
static int vbus_state = -1;
#ifdef CONFIG_USB_MUSB_HDRC_HCD
#define portstate(stmt) stmt
#else
#define portstate(stmt)
#endif
static void session(struct musb *musb, int is_on)
{
void *__iomem mregs = musb->pRegs;
u8 devctl = musb_readb(mregs, MGC_O_HDRC_DEVCTL);
/* NOTE: after drvvbus off the state _could_ be A_IDLE;
* but the silicon seems to couple vbus to "ID grounded".
*/
devctl |= MGC_M_DEVCTL_SESSION;
if (is_on) {
musb->xceiv.state = OTG_STATE_A_WAIT_BCON;
portstate(musb->port1_status |= USB_PORT_STAT_POWER);
} else {
musb->xceiv.state = OTG_STATE_B_IDLE;
portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
}
musb_writeb(mregs, MGC_O_HDRC_DEVCTL, devctl);
}
/* VBUS SWITCHING IS BOARD-SPECIFIC */
#ifdef CONFIG_MACH_DAVINCI_EVM
/* I2C operations are always synchronous, and require a task context.
* With unloaded systems, using the shared workqueue seems to suffice
* to satisfy the 100msec A_WAIT_VRISE timeout...
*/
static void evm_deferred_drvvbus(void *_musb)
{
struct musb *musb = _musb;
int is_on = (musb->xceiv.state == OTG_STATE_A_WAIT_VRISE);
davinci_i2c_expander_op(0x3a, USB_DRVVBUS, !is_on);
vbus_state = is_on;
session(musb, is_on);
}
DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus, 0);
#endif
static void davinci_vbus_power(struct musb *musb, int is_on, int sleeping)
{
if (is_on)
is_on = 1;
if (vbus_state == is_on)
return;
if (is_on) {
musb->xceiv.state = OTG_STATE_A_WAIT_VRISE;
MUSB_HST_MODE(musb);
} else {
switch (musb->xceiv.state) {
case OTG_STATE_UNDEFINED:
case OTG_STATE_B_IDLE:
MUSB_DEV_MODE(musb);
musb->xceiv.state = OTG_STATE_B_IDLE;
break;
case OTG_STATE_A_IDLE:
break;
default:
musb->xceiv.state = OTG_STATE_A_WAIT_VFALL;
break;
}
}
#ifdef CONFIG_MACH_DAVINCI_EVM
if (machine_is_davinci_evm()) {
#ifdef CONFIG_MACH_DAVINCI_EVM_OTG
/* modified EVM board switching VBUS with GPIO(6) not I2C
* NOTE: PINMUX0.RGB888 (bit23) must be clear
*/
if (is_on)
gpio_set(GPIO(6));
else
gpio_clear(GPIO(6));
#else
if (sleeping)
davinci_i2c_expander_op(0x3a, USB_DRVVBUS, !is_on);
else
schedule_work(&evm_vbus_work);
#endif
}
#endif
if (sleeping) {
vbus_state = is_on;
session(musb, is_on);
}
DBG(2, "VBUS power %s, %s\n", is_on ? "on" : "off",
sleeping ? "immediate" : "deferred");
}
static irqreturn_t davinci_interrupt(int irq, void *__hci, struct pt_regs *r)
{
unsigned long flags;
irqreturn_t retval = IRQ_NONE;
struct musb *musb = __hci;
void *__iomem tibase = musb->ctrl_base;
u32 tmp;
spin_lock_irqsave(&musb->Lock, flags);
/* NOTE: DaVinci shadows the Mentor IRQs. Don't manage them through
* the Mentor registers (except for setup), use the TI ones and EOI.
*
* Docs describe irq "vector" registers asociated with the CPPI and
* USB EOI registers. These hold a bitmask corresponding to the
* current IRQ, not an irq handler address. Would using those bits
* resolve some of the races observed in this dispatch code??
*/
#ifdef CONFIG_USB_TI_CPPI_DMA
/* CPPI interrupts share the same IRQ line, but have their own
* mask, state, "vector", and EOI registers.
*/
{
u32 cppi_tx = musb_readl(tibase, DAVINCI_TXCPPI_MASKED_REG);
u32 cppi_rx = musb_readl(tibase, DAVINCI_RXCPPI_MASKED_REG);
if (cppi_tx || cppi_rx) {
DBG(4, "<== CPPI IRQ t%x r%x\n", cppi_tx, cppi_rx);
cppi_completion(musb, cppi_rx, cppi_tx);
retval = IRQ_HANDLED;
}
}
#endif
/* ack and handle non-CPPI interrupts */
tmp = musb_readl(tibase, DAVINCI_USB_INT_SRC_MASKED_REG);
musb_writel(tibase, DAVINCI_USB_INT_SRC_CLR_REG, tmp);
musb->int_rx = (tmp & DAVINCI_USB_RXINT_MASK)
>> DAVINCI_USB_RXINT_SHIFT;
musb->int_tx = (tmp & DAVINCI_USB_TXINT_MASK)
>> DAVINCI_USB_TXINT_SHIFT;
musb->int_usb = (tmp & DAVINCI_USB_USBINT_MASK)
>> DAVINCI_USB_USBINT_SHIFT;
musb->int_regs = r;
if (tmp & (1 << (8 + DAVINCI_USB_USBINT_SHIFT))) {
int drvvbus = musb_readl(tibase, DAVINCI_USB_STAT_REG);
/* NOTE: this must complete poweron within 100 msec */
davinci_vbus_power(musb, drvvbus, 0);
DBG(2, "DRVVBUS %d (state %d)\n", drvvbus, musb->xceiv.state);
retval = IRQ_HANDLED;
}
if (musb->int_tx || musb->int_rx || musb->int_usb)
retval |= musb_interrupt(musb);
/* irq stays asserted until EOI is written */
musb_writel(tibase, DAVINCI_USB_EOI_REG, 0);
musb->int_regs = NULL;
spin_unlock_irqrestore(&musb->Lock, flags);
/* REVISIT we sometimes get unhandled IRQs
* (e.g. ep0). not clear why...
*/
if (retval != IRQ_HANDLED)
DBG(5, "unhandled? %08x\n", tmp);
return IRQ_HANDLED;
}
int __devinit musb_platform_init(struct musb *musb)
{
void *__iomem tibase = musb->ctrl_base;
u32 revision;
musb->pRegs += DAVINCI_BASE_OFFSET;
#if 0
/* REVISIT there's something odd about clocking, this
* didn't appear do the job ...
*/
musb->clock = clk_get(pDevice, "usb");
if (IS_ERR(musb->clock))
return PTR_ERR(musb->clock);
status = clk_enable(musb->clock);
if (status < 0)
return -ENODEV;
#endif
/* returns zero if e.g. not clocked */
revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG);
if (revision == 0)
return -ENODEV;
/* note that transceiver issues make us want to charge
* VBUS only when the PHY PLL is not active.
*/
#ifdef CONFIG_MACH_DAVINCI_EVM
evm_vbus_work.data = musb;
#endif
davinci_vbus_power(musb, musb->board_mode == MUSB_HOST, 1);
/* reset the controller */
musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1);
/* start the on-chip PHY and its PLL */
phy_on();
msleep(5);
/* NOTE: irqs are in mixed mode, not bypass to pure-musb */
pr_debug("DaVinci OTG revision %08x phy %03x control %02x\n",
revision,
musb_readl((void *__iomem) IO_ADDRESS(
USBPHY_CTL_PADDR), 0x00),
musb_readb(tibase, DAVINCI_USB_CTRL_REG));
musb->isr = davinci_interrupt;
return 0;
}
int musb_platform_exit(struct musb *musb)
{
phy_off();
davinci_vbus_power(musb, 0 /*off*/, 1);
return 0;
}
/*
* Copyright (C) 2005-2006 by Texas Instruments
*
* 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.
*/
#ifndef __MUSB_HDRDF_H__
#define __MUSB_HDRDF_H__
/*
* DaVinci-specific definitions
*/
/* Integrated highspeed/otg PHY */
#define USBPHY_CTL_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x34)
#define USBPHY_PHYCLKGD (1 << 8)
#define USBPHY_SESNDEN (1 << 7) /* v(sess_end) comparator */
#define USBPHY_VBDTCTEN (1 << 6) /* v(bus) comparator */
#define USBPHY_PHYPLLON (1 << 4) /* override pll suspend */
#define USBPHY_CLK01SEL (1 << 3)
#define USBPHY_OSCPDWN (1 << 2)
#define USBPHY_PHYSPDWN (1 << 0)
/* For now include usb OTG module registers here */
#define DAVINCI_USB_VERSION_REG 0x00
#define DAVINCI_USB_CTRL_REG 0x04
#define DAVINCI_USB_STAT_REG 0x08
#define DAVINCI_RNDIS_REG 0x10
#define DAVINCI_AUTOREQ_REG 0x14
#define DAVINCI_USB_INT_SOURCE_REG 0x20
#define DAVINCI_USB_INT_SET_REG 0x24
#define DAVINCI_USB_INT_SRC_CLR_REG 0x28
#define DAVINCI_USB_INT_MASK_REG 0x2c
#define DAVINCI_USB_INT_MASK_SET_REG 0x30
#define DAVINCI_USB_INT_MASK_CLR_REG 0x34
#define DAVINCI_USB_INT_SRC_MASKED_REG 0x38
#define DAVINCI_USB_EOI_REG 0x3c
#define DAVINCI_USB_EOI_INTVEC 0x40
/* CPPI related registers */
#define DAVINCI_TXCPPI_CTRL_REG 0x80
#define DAVINCI_TXCPPI_TEAR_REG 0x84
#define DAVINCI_CPPI_EOI_REG 0x88
#define DAVINCI_CPPI_INTVEC_REG 0x8c
#define DAVINCI_TXCPPI_MASKED_REG 0x90
#define DAVINCI_TXCPPI_RAW_REG 0x94
#define DAVINCI_TXCPPI_INTENAB_REG 0x98
#define DAVINCI_TXCPPI_INTCLR_REG 0x9c
#define DAVINCI_RXCPPI_CTRL_REG 0xC0
#define DAVINCI_RXCPPI_MASKED_REG 0xD0
#define DAVINCI_RXCPPI_RAW_REG 0xD4
#define DAVINCI_RXCPPI_INTENAB_REG 0xD8
#define DAVINCI_RXCPPI_INTCLR_REG 0xDC
#define DAVINCI_RXCPPI_BUFCNT0_REG 0xE0
#define DAVINCI_RXCPPI_BUFCNT1_REG 0xE4
#define DAVINCI_RXCPPI_BUFCNT2_REG 0xE8
#define DAVINCI_RXCPPI_BUFCNT3_REG 0xEC
/* CPPI state RAM entries */
#define DAVINCI_CPPI_STATERAM_BASE_OFFSET 0x100
#define DAVINCI_TXCPPI_STATERAM_OFFSET(channelNum) \
(DAVINCI_CPPI_STATERAM_BASE_OFFSET + ((channelNum)* 0x40))
#define DAVINCI_RXCPPI_STATERAM_OFFSET(channelNum) \
(DAVINCI_CPPI_STATERAM_BASE_OFFSET + 0x20 +((channelNum)* 0x40))
/* CPPI masks */
#define DAVINCI_DMA_CTRL_ENABLE 1
#define DAVINCI_DMA_CTRL_DISABLE 0
#define DAVINCI_DMA_ALL_CHANNELS_ENABLE 0xF
#define DAVINCI_DMA_ALL_CHANNELS_DISABLE 0xF
/* REVISIT relying on "volatile" here is wrong ... */
/* define structures of Rx/Tx stateRam entries */
struct cppi_tx_stateram {
volatile u32 headPtr;
volatile u32 sopDescPtr;
volatile u32 currDescPtr;
volatile u32 currBuffPtr;
volatile u32 flags;
volatile u32 remLength;
volatile u32 dummy;
volatile u32 completionPtr;
};
struct cppi_rx_stateram {
volatile u32 buffOffset;
volatile u32 headPtr;
volatile u32 sopDescPtr;
volatile u32 currDescPtr;
volatile u32 currBuffPtr;
volatile u32 pktLength;
volatile u32 byteCount;
volatile u32 completionPtr;
};
#define DAVINCI_USB_TX_ENDPTS_MASK 0x1f /* ep0 + 4 tx */
#define DAVINCI_USB_RX_ENDPTS_MASK 0x1e /* 4 rx */
#define DAVINCI_USB_USBINT_SHIFT 16
#define DAVINCI_USB_TXINT_SHIFT 0
#define DAVINCI_USB_RXINT_SHIFT 8
#define DAVINCI_USB_USBINT_MASK 0x01ff0000 /* 8 Mentor, DRVVBUS */
#define DAVINCI_USB_TXINT_MASK \
(DAVINCI_USB_TX_ENDPTS_MASK << DAVINCI_USB_TXINT_SHIFT)
#define DAVINCI_USB_RXINT_MASK \
(DAVINCI_USB_RX_ENDPTS_MASK << DAVINCI_USB_RXINT_SHIFT)
#define DAVINCI_BASE_OFFSET 0x400
#endif /* __MUSB_HDRDF_H__ */
/******************************************************************
* Copyright 2005 Mentor Graphics Corporation
* Copyright (C) 2005-2006 by Texas Instruments
*
* 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
*
* ANY DOWNLOAD, USE, REPRODUCTION, MODIFICATION OR DISTRIBUTION
* OF THIS DRIVER INDICATES YOUR COMPLETE AND UNCONDITIONAL ACCEPTANCE
* OF THOSE TERMS.THIS DRIVER IS PROVIDED "AS IS" AND MENTOR GRAPHICS
* MAKES NO WARRANTIES, EXPRESS OR IMPLIED, RELATED TO THIS DRIVER.
* MENTOR GRAPHICS SPECIFICALLY DISCLAIMS ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY; FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. MENTOR GRAPHICS DOES NOT PROVIDE SUPPORT
* SERVICES OR UPDATES FOR THIS DRIVER, EVEN IF YOU ARE A MENTOR
* GRAPHICS SUPPORT CUSTOMER.
******************************************************************/
#ifndef __MUSB_LINUX_DEBUG_H__
#define __MUSB_LINUX_DEBUG_H__
#define yprintk(facility, format, args...) \
do { printk(facility "%s %d: " format , \
__FUNCTION__, __LINE__ , ## args); } while (0)
#define WARN(fmt, args...) yprintk(KERN_WARNING,fmt, ## args)
#define INFO(fmt,args...) yprintk(KERN_INFO,fmt, ## args)
#define ERR(fmt,args...) yprintk(KERN_ERR,fmt, ## args)
#define xprintk(level, facility, format, args...) do { \
if ( _dbg_level(level) ) { \
printk(facility "%s %d: " format , \
__FUNCTION__, __LINE__ , ## args); \
} } while (0)
#if MUSB_DEBUG > 0
extern unsigned debug;
#else
#define debug 0
#endif
static inline int _dbg_level(unsigned l)
{
return debug >= l;
}
#define DBG(level,fmt,args...) xprintk(level,KERN_DEBUG,fmt, ## args)
#endif // __MUSB_LINUX_DEBUG_H__
/******************************************************************
* Copyright 2005 Mentor Graphics Corporation
* Copyright (C) 2005-2006 by Texas Instruments
*
* 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
*
* ANY DOWNLOAD, USE, REPRODUCTION, MODIFICATION OR DISTRIBUTION
* OF THIS DRIVER INDICATES YOUR COMPLETE AND UNCONDITIONAL ACCEPTANCE
* OF THOSE TERMS.THIS DRIVER IS PROVIDED "AS IS" AND MENTOR GRAPHICS
* MAKES NO WARRANTIES, EXPRESS OR IMPLIED, RELATED TO THIS DRIVER.
* MENTOR GRAPHICS SPECIFICALLY DISCLAIMS ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY; FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. MENTOR GRAPHICS DOES NOT PROVIDE SUPPORT
* SERVICES OR UPDATES FOR THIS DRIVER, EVEN IF YOU ARE A MENTOR
* GRAPHICS SUPPORT CUSTOMER.
******************************************************************/
#ifndef __MUSB_DMA_H__
#define __MUSB_DMA_H__
struct musb_hw_ep;
/*
* DMA Controller Abstraction
*
* DMA Controllers are abstracted to allow use of a variety of different
* implementations of DMA, as allowed by the Inventra USB cores. On the
* host side, usbcore sets up the DMA mappings and flushes caches; on the
* peripheral side, the gadget controller driver does. Responsibilities
* of a DMA controller driver include:
*
* - Handling the details of moving multiple USB packets
* in cooperation with the Inventra USB core, including especially
* the correct RX side treatment of short packets and buffer-full
* states (both of which terminate transfers).
*
* - Knowing the correlation between dma channels and the
* Inventra core's local endpoint resources and data direction.
*
* - Maintaining a list of allocated/available channels.
*
* - Updating channel status on interrupts,
* whether shared with the Inventra core or separate.
*/
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
#ifndef CONFIG_USB_INVENTRA_FIFO
#define is_dma_capable() (1)
#else
#define is_dma_capable() (0)
#endif
#if defined(CONFIG_USB_TI_CPPI_DMA) && defined(CONFIG_USB_MUSB_HDRC_HCD)
extern void cppi_hostdma_start(struct musb * pThis, u8 bEnd);
#else
static inline void cppi_hostdma_start(struct musb * pThis, u8 bEnd) {}
#endif
/*
* DMA channel status ... updated by the dma controller driver whenever that
* status changes, and protected by the overall controller spinlock.
*/
enum dma_channel_status {
/* unallocated */
MGC_DMA_STATUS_UNKNOWN,
/* allocated ... but not busy, no errors */
MGC_DMA_STATUS_FREE,
/* busy ... transactions are active */
MGC_DMA_STATUS_BUSY,
/* transaction(s) aborted due to ... dma or memory bus error */
MGC_DMA_STATUS_BUS_ABORT,
/* transaction(s) aborted due to ... core error or USB fault */
MGC_DMA_STATUS_CORE_ABORT
};
struct dma_controller;
/**
* struct dma_channel - A DMA channel.
* @pPrivateData: channel-private data
* @wMaxLength: the maximum number of bytes the channel can move in one
* transaction (typically representing many USB maximum-sized packets)
* @dwActualLength: how many bytes have been transferred
* @bStatus: current channel status (updated e.g. on interrupt)
* @bDesiredMode: TRUE if mode 1 is desired; FALSE if mode 0 is desired
*
* channels are associated with an endpoint for the duration of at least
* one usb transfer.
*/
struct dma_channel {
void *pPrivateData;
// FIXME not void* private_data, but a dma_controller *
size_t dwMaxLength;
size_t dwActualLength;
enum dma_channel_status bStatus;
u8 bDesiredMode;
};
/*
* Program a DMA channel to move data at the core's request.
* The local core endpoint and direction should already be known,
* since they are specified in the channel_alloc call.
*
* @channel: pointer to a channel obtained by channel_alloc
* @maxpacket: the maximum packet size
* @bMode: TRUE if mode 1; FALSE if mode 0
* @dma_addr: base address of data (in DMA space)
* @length: the number of bytes to transfer; no larger than the channel's
* reported dwMaxLength
*
* Returns TRUE on success, else FALSE
*/
typedef int (*MGC_pfDmaProgramChannel) (
struct dma_channel *channel,
u16 maxpacket,
u8 bMode,
dma_addr_t dma_addr,
u32 length);
/*
* dma_channel_status - return status of dma channel
* @c: the channel
*
* Returns the software's view of the channel status. If that status is BUSY
* then it's possible that the hardware has completed (or aborted) a transfer,
* so the driver needs to update that status.
*/
static inline enum dma_channel_status
dma_channel_status(struct dma_channel *c)
{
return (is_dma_capable() && c) ? c->bStatus : MGC_DMA_STATUS_UNKNOWN;
}
/**
* struct dma_controller - A DMA Controller.
* @pPrivateData: controller-private data;
* @start: call this to start a DMA controller;
* return 0 on success, else negative errno
* @stop: call this to stop a DMA controller
* return 0 on success, else negative errno
* @channel_alloc: call this to allocate a DMA channel
* @channel_release: call this to release a DMA channel
* @channel_abort: call this to abort a pending DMA transaction,
* returning it to FREE (but allocated) state
*
* Controllers manage dma channels.
*/
struct dma_controller {
void *pPrivateData;
int (*start)(struct dma_controller *);
int (*stop)(struct dma_controller *);
struct dma_channel *(*channel_alloc)(struct dma_controller *,
struct musb_hw_ep *, u8 is_tx);
void (*channel_release)(struct dma_channel *);
MGC_pfDmaProgramChannel channel_program;
int (*channel_abort)(struct dma_channel *);
};
/* called after channel_program(), may indicate a fault */
extern void musb_dma_completion(struct musb *musb, u8 bLocalEnd, u8 bTransmit);
/**
* struct dma_controller_factory - DMA controller factory
* @create: create a DMA controller
* @destroy: destroy a DMA controller
*
* To allow for multi-core implementations and different
* types of cores and DMA controllers to co-exist,
* (only at the source level; no runtime coexistence supported)
* it is necessary to create them from factories.
*/
struct dma_controller_factory {
struct dma_controller *(*create)(struct musb *, void __iomem *);
void (*destroy)(struct dma_controller *);
};
extern const struct dma_controller_factory dma_controller_factory;
#endif /* __MUSB_DMA_H__ */
This diff is collapsed.
This diff is collapsed.
/******************************************************************
* Copyright 2005 Mentor Graphics Corporation
* Copyright (C) 2005-2006 by Texas Instruments
*
* 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
*
* ANY DOWNLOAD, USE, REPRODUCTION, MODIFICATION OR DISTRIBUTION
* OF THIS DRIVER INDICATES YOUR COMPLETE AND UNCONDITIONAL ACCEPTANCE
* OF THOSE TERMS.THIS DRIVER IS PROVIDED "AS IS" AND MENTOR GRAPHICS
* MAKES NO WARRANTIES, EXPRESS OR IMPLIED, RELATED TO THIS DRIVER.
* MENTOR GRAPHICS SPECIFICALLY DISCLAIMS ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY; FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. MENTOR GRAPHICS DOES NOT PROVIDE SUPPORT
* SERVICES OR UPDATES FOR THIS DRIVER, EVEN IF YOU ARE A MENTOR
* GRAPHICS SUPPORT CUSTOMER.
******************************************************************/
#ifndef __MUSB_GADGET_H
#define __MUSB_GADGET_H
struct musb_request {
struct usb_request request;
struct musb_ep *ep;
struct musb *musb;
u8 bTx; /* endpoint direction */
u8 bEnd;
u8 mapped;
};
static inline struct musb_request *to_musb_request(struct usb_request *req)
{
return req ? container_of(req, struct musb_request, request) : NULL;
}
extern struct usb_request *
musb_alloc_request(struct usb_ep *ep, gfp_t gfp_flags);
extern void musb_free_request(struct usb_ep *ep, struct usb_request *req);
/*
* struct musb_ep - peripheral side view of endpoint rx or tx side
*/
struct musb_ep {
/* stuff towards the head is basically write-once. */
struct usb_ep end_point;
char name[12];
struct musb_hw_ep *hw_ep;
struct musb *pThis;
u8 bEndNumber;
/* ... when enabled/disabled ... */
u8 type;
u8 is_in;
u16 wPacketSize;
const struct usb_endpoint_descriptor *desc;
struct dma_channel *dma;
/* later things are modified based on usage */
struct list_head req_list;
u8 busy;
};
static inline struct musb_ep *to_musb_ep(struct usb_ep *ep)
{
return ep ? container_of(ep, struct musb_ep, end_point) : NULL;
}
static inline struct usb_request *next_request(struct musb_ep *ep)
{
struct list_head *queue = &ep->req_list;
if (list_empty(queue))
return NULL;
return container_of(queue->next, struct usb_request, list);
}
extern void musb_g_tx(struct musb *pThis, u8 bEnd);
extern void musb_g_rx(struct musb *pThis, u8 bEnd);
extern struct usb_ep_ops musb_g_ep0_ops;
extern int musb_gadget_setup(struct musb *);
extern void musb_gadget_cleanup(struct musb *);
extern void musb_g_giveback(struct musb_ep *, struct usb_request *, int);
extern int musb_gadget_set_halt(struct usb_ep *ep, int value);
#endif /* __MUSB_GADGET_H */
This diff is collapsed.
/******************************************************************
* Copyright 2005 Mentor Graphics Corporation
* Copyright (C) 2005-2006 by Texas Instruments
*
* 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
*
* ANY DOWNLOAD, USE, REPRODUCTION, MODIFICATION OR DISTRIBUTION
* OF THIS DRIVER INDICATES YOUR COMPLETE AND UNCONDITIONAL ACCEPTANCE
* OF THOSE TERMS.THIS DRIVER IS PROVIDED "AS IS" AND MENTOR GRAPHICS
* MAKES NO WARRANTIES, EXPRESS OR IMPLIED, RELATED TO THIS DRIVER.
* MENTOR GRAPHICS SPECIFICALLY DISCLAIMS ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY; FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. MENTOR GRAPHICS DOES NOT PROVIDE SUPPORT
* SERVICES OR UPDATES FOR THIS DRIVER, EVEN IF YOU ARE A MENTOR
* GRAPHICS SUPPORT CUSTOMER.
******************************************************************/
#ifndef _MUSB_HOST_H
#define _MUSB_HOST_H
static inline struct usb_hcd *musb_to_hcd(struct musb *musb)
{
return (struct usb_hcd *) (((void *)musb)
- offsetof(struct usb_hcd, hcd_priv));
}
static inline struct musb *hcd_to_musb(struct usb_hcd *hcd)
{
return (void *) hcd->hcd_priv;
}
/* stored in "usb_host_endpoint.hcpriv" for scheduled endpoints
*/
struct musb_qh {
struct usb_host_endpoint *hep; /* usbcore info */
struct usb_device *dev;
struct musb_hw_ep *hw_ep; /* current binding */
struct list_head ring; /* of musb_qh */
//struct musb_qh *next; /* for periodic tree */
unsigned offset; /* in urb->transfer_buffer */
unsigned segsize; /* current xfer fragment */
u8 type_reg; /* {rx,tx} type register */
u8 intv_reg; /* {rx,tx} interval register */
u8 addr_reg; /* device address register */
u8 h_addr_reg; /* hub address register */
u8 h_port_reg; /* hub port register */
u8 is_ready; /* safe to modify hw_ep */
u8 type; /* XFERTYPE_* */
u8 epnum;
u16 maxpacket;
u16 frame; /* for periodic schedule */
unsigned iso_idx; /* in urb->iso_frame_desc[] */
};
/* map from control or bulk queue head to the first qh on that ring */
static inline struct musb_qh *first_qh(struct list_head *q)
{
if (list_empty(q))
return NULL;
return container_of(q->next, struct musb_qh, ring);
}
extern void musb_h_tx_start(struct musb *, u8 bEnd);
extern void musb_root_disconnect(struct musb *musb);
struct usb_hcd;
extern int musb_hub_status_data(struct usb_hcd *hcd, char *buf);
extern int musb_hub_control(struct usb_hcd *hcd,
u16 typeReq, u16 wValue, u16 wIndex,
char *buf, u16 wLength);
extern int musb_bus_suspend(struct usb_hcd *);
extern int musb_bus_resume(struct usb_hcd *);
extern const struct hc_driver musb_hc_driver;
static inline struct urb *next_urb(struct musb_qh *qh)
{
#ifdef CONFIG_USB_MUSB_HDRC_HCD
struct list_head *queue;
if (!qh)
return NULL;
queue = &qh->hep->urb_list;
if (list_empty(queue))
return NULL;
return container_of(queue->next, struct urb, urb_list);
#else
return NULL;
#endif
}
#endif /* _MUSB_HOST_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (C) 2005-2006 by Texas Instruments
*
* 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/config.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/clk.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/mach-types.h>
#include <asm/arch/hardware.h>
#include <asm/arch/mux.h>
#include "musbdefs.h"
#include "omap2430.h"
static int dma_off;
void musb_platform_enable(struct musb *musb)
{
if (is_dma_capable() && dma_off)
printk(KERN_WARNING "%s %s: dma not reactivated\n",
__FILE__, __FUNCTION__);
else
dma_off = 1;
}
void musb_platform_disable(struct musb *musb)
{
if (is_dma_capable()) {
printk(KERN_WARNING "%s %s: dma still active\n",
__FILE__, __FUNCTION__);
dma_off = 1;
}
}
static void omap_vbus_power(struct musb *musb, int is_on, int sleeping)
{
}
int __devinit musb_platform_init(struct musb *musb)
{
/* Erratum - reset value of STP has pull-down.
Change it to pull-up. */
omap2_cfg_reg(AE5_2430_USB0HS_STP);
/* start clock */
musb->clock = clk_get((struct device *)musb->controller, "usbhs_ick");
clk_use(musb->clock);
omap_writel(omap_readl(OTG_INTERFSEL) | (1<<0), OTG_INTERFSEL);
omap_writel(omap_readl(OTG_SYSCONFIG) |
((1 << 12) | (1 << 3) | (1 << 2)),
OTG_SYSCONFIG);
pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
"sysstatus 0x%x, intrfsel 0x%x, simenable 0x%x\n",
omap_readl(OTG_REVISION), omap_readl(OTG_SYSCONFIG),
omap_readl(OTG_SYSSTATUS), omap_readl(OTG_INTERFSEL),
omap_readl(OTG_SIMENABLE));
omap_vbus_power(musb, musb->board_mode == MUSB_HOST, 1);
return 0;
}
int __exit musb_platform_exit(struct musb *musb)
{
omap_vbus_power(musb, 0 /*off*/, 1);
/* REVISIT older omap trees need "unuse", more current
* ones just have disable()
*/
clk_unuse(musb->clock);
return 0;
}
/*
* Copyright (C) 2005-2006 by Texas Instruments
*
* 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.
*/
#ifndef __MUSB_OMAP243X_H__
#define __MUSB_OMAP243X_H__
#ifdef CONFIG_ARCH_OMAP243X
/*
* OMAP2430-specific definitions
*/
#define MENTOR_BASE_OFFSET 0
#define HS_OTG(offset) (OMAP243X_HS_BASE + (offset))
#define OTG_REVISION HS_OTG(0x400)
#define OTG_SYSCONFIG HS_OTG(0x404)
#define OTG_SYSSTATUS HS_OTG(0x408)
#define OTG_INTERFSEL HS_OTG(0x40c)
#define OTG_SIMENABLE HS_OTG(0x410)
#endif /* CONFIG_ARCH_OMAP243X */
#endif /* __MUSB_OMAP243X_H__ */
This diff is collapsed.
/******************************************************************
* Copyright 2005 Mentor Graphics Corporation
* Copyright (C) 2005-2006 by Texas Instruments
*
* 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
*
* ANY DOWNLOAD, USE, REPRODUCTION, MODIFICATION OR DISTRIBUTION
* OF THIS DRIVER INDICATES YOUR COMPLETE AND UNCONDITIONAL ACCEPTANCE
* OF THOSE TERMS.THIS DRIVER IS PROVIDED "AS IS" AND MENTOR GRAPHICS
* MAKES NO WARRANTIES, EXPRESS OR IMPLIED, RELATED TO THIS DRIVER.
* MENTOR GRAPHICS SPECIFICALLY DISCLAIMS ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY; FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. MENTOR GRAPHICS DOES NOT PROVIDE SUPPORT
* SERVICES OR UPDATES FOR THIS DRIVER, EVEN IF YOU ARE A MENTOR
* GRAPHICS SUPPORT CUSTOMER.
******************************************************************/
/*
* Interface to a generic OTG state machine for use by an OTG controller.
*
* FIXME most of this must vanish; usbcore handles some of it, and
* the OTG parts of a peripheral controller (and its driver) handle
* other things. Package it as an "otg transceiver".
*/
#ifndef __MUSB_LINUX_OTG_H__
#define __MUSB_LINUX_OTG_H__
#include <linux/spinlock.h>
#include <linux/timer.h>
/**
* Introduction.
* An OTG state machine for use by a controller driver for an OTG controller
* that wishes to be OTG-aware.
* The state machine requires relevant inputs and a couple of services
* from the controller driver, and calls the controller driver to inform
* it of the current state and errors.
* Finally, it provides the necessary bus control service.
*/
/****************************** CONSTANTS ********************************/
/*
* Define this (in milliseconds) to a target-specific value to override default.
* The OTG-spec minimum is 5000, and maximum is 6000 (see OTG spec errata).
*/
#ifndef MGC_OTG_T_B_SRP_FAIL
#define MGC_OTG_T_B_SRP_FAIL 5000
#endif
/*
* Define this (in milliseconds) to a target-specific value to override default.
* This is the time an A-device should wait for a B-device to connect.
* The OTG-spec minimum is 1000.
* As a special case, for normal host-like behavior, you can set this to 0.
*/
#ifndef MGC_OTG_T_A_WAIT_BCON
#define MGC_OTG_T_A_WAIT_BCON 1000
#endif
/*
* Define this (in milliseconds) to a target-specific value to override default.
* The OTG-spec minimum is 250.
*/
#ifndef MGC_OTG_T_AIDL_BDIS
#define MGC_OTG_T_AIDL_BDIS 250
#endif
//#define MGC_OTG_T_B_ASE0_BRST 4
#define MGC_OTG_T_B_ASE0_BRST 100
/*
* MGC_OtgRequest.
* A software request for the OTG state machine
*/
typedef enum {
MGC_OTG_REQUEST_UNKNOWN,
/** Request the bus */
MGC_OTG_REQUEST_START_BUS,
/** Drop the bus */
MGC_OTG_REQUEST_DROP_BUS,
/** Suspend the bus */
MGC_OTG_REQUEST_SUSPEND_BUS,
/** Reset the state machine */
MGC_OTG_REQUEST_RESET
} MGC_OtgRequest;
/******************************** TYPES **********************************/
/*
* MGC_OtgMachineInputs.
* The set of inputs which drives the state machine
* @field bSession TRUE when a session is in progress; FALSE when not
* @field bConnectorId TRUE for B-device; FALSE for A-device
* (assumed valid only when a bSession is TRUE)
* @field bReset TRUE when reset is detected (peripheral role only)
* @field bConnection TRUE when connection is detected (host role only)
* @field bSuspend TRUE when bus suspend is detected
* @field bVbusError TRUE when a Vbus error is detected
*/
typedef struct {
u8 bSession;
u8 bConnectorId;
u8 bReset;
u8 bConnection;
u8 bSuspend;
u8 bVbusError;
} MGC_OtgMachineInputs;
/*
* OTG state machine instance data.
* @field Lock spinlock
* @field bState current state (one of the OTG_STATE_* constants)
* @field pOtgServices pointer to OTG services
* @field Timer interval timer for status change interrupts
* @field bState current state
* @field bRequest current pending request
*/
struct otg_machine {
spinlock_t Lock;
struct musb *musb;
enum usb_otg_state bState;
struct timer_list Timer;
MGC_OtgRequest bRequest;
/* FIXME standard Linux-USB host and peripheral code includes
* OTG support ... most of this "otg machine" must vanish
*/
};
/****************************** FUNCTIONS ********************************/
/*
* Initialize an OTG state machine.
*/
extern void MGC_OtgMachineInit(struct otg_machine * pMachine,
struct musb *musb);
/*
* Destroy an OTG state machine
* @param pMachine machine pointer
* @see #MGC_OtgMachineInit
*/
extern void MGC_OtgMachineDestroy(struct otg_machine * pMachine);
/*
* OTG inputs have changed.
* A controller driver calls this when anything in the
* MGC_OtgMachineInputs has changed
* @param pMachine machine pointer
* @param pInputs current inputs
* @see #MGC_OtgMachineInit
*/
extern void MGC_OtgMachineInputsChanged(struct otg_machine * pMachine,
const MGC_OtgMachineInputs * pInputs);
#endif /* multiple inclusion protection */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment