usb: musb: add support for Blackfin MUSB

Signed-off-by: Bryan Wu <bryan.wu@analog.com>
Signed-off-by: Cliff Cai <cliff.cai@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Remy Bohmer <linux@bohmer.net>
This commit is contained in:
Bryan Wu 2009-12-16 22:04:02 -05:00 committed by Remy Bohmer
parent bc72a919e0
commit e608f221c1
7 changed files with 528 additions and 2 deletions

View File

@ -27,6 +27,7 @@ LIB := $(obj)libusb_musb.a
COBJS-$(CONFIG_MUSB_HCD) += musb_hcd.o musb_core.o
COBJS-$(CONFIG_MUSB_UDC) += musb_udc.o musb_core.o
COBJS-$(CONFIG_USB_BLACKFIN) += blackfin_usb.o
COBJS-$(CONFIG_USB_DAVINCI) += davinci.o
COBJS-$(CONFIG_USB_OMAP3) += omap3.o
COBJS-$(CONFIG_USB_DA8XX) += da8xx.o

View File

@ -0,0 +1,143 @@
/*
* Blackfin MUSB HCD (Host Controller Driver) for u-boot
*
* Copyright (c) 2008-2009 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
#include <common.h>
#include <usb.h>
#include <asm/blackfin.h>
#include <asm/mach-common/bits/usb.h>
#include "musb_core.h"
/* MUSB platform configuration */
struct musb_config musb_cfg = {
.regs = (struct musb_regs *)USB_FADDR,
.timeout = 0x3FFFFFF,
.musb_speed = 0,
};
/*
* This function read or write data to endpoint fifo
* Blackfin use DMA polling method to avoid buffer alignment issues
*
* ep - Endpoint number
* length - Number of bytes to write to FIFO
* fifo_data - Pointer to data buffer to be read/write
* is_write - Flag for read or write
*/
void rw_fifo(u8 ep, u32 length, void *fifo_data, int is_write)
{
struct bfin_musb_dma_regs *regs;
u32 val = (u32)fifo_data;
blackfin_dcache_flush_invalidate_range(fifo_data, fifo_data + length);
regs = (void *)USB_DMA_INTERRUPT;
regs += ep;
/* Setup DMA address register */
bfin_write16(&regs->addr_low, val);
SSYNC();
bfin_write16(&regs->addr_high, val >> 16);
SSYNC();
/* Setup DMA count register */
bfin_write16(&regs->count_low, length);
bfin_write16(&regs->count_high, 0);
SSYNC();
/* Enable the DMA */
val = (ep << 4) | DMA_ENA | INT_ENA;
if (is_write)
val |= DIRECTION;
bfin_write16(&regs->control, val);
SSYNC();
/* Wait for compelete */
while (!(bfin_read_USB_DMA_INTERRUPT() & (1 << ep)))
continue;
/* acknowledge dma interrupt */
bfin_write_USB_DMA_INTERRUPT(1 << ep);
SSYNC();
/* Reset DMA */
bfin_write16(&regs->control, 0);
SSYNC();
}
void write_fifo(u8 ep, u32 length, void *fifo_data)
{
rw_fifo(ep, length, fifo_data, 1);
}
void read_fifo(u8 ep, u32 length, void *fifo_data)
{
rw_fifo(ep, length, fifo_data, 0);
}
/*
* CPU and board-specific MUSB initializations. Aliased function
* signals caller to move on.
*/
static void __def_musb_init(void)
{
}
void board_musb_init(void) __attribute__((weak, alias("__def_musb_init")));
int musb_platform_init(void)
{
/* board specific initialization */
board_musb_init();
if (ANOMALY_05000346) {
bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value);
SSYNC();
}
if (ANOMALY_05000347) {
bfin_write_USB_APHY_CNTRL(0x0);
SSYNC();
}
/* Configure PLL oscillator register */
bfin_write_USB_PLLOSC_CTRL(0x30a8);
SSYNC();
bfin_write_USB_SRP_CLKDIV((get_sclk()/1000) / 32 - 1);
SSYNC();
bfin_write_USB_EP_NI0_RXMAXP(64);
SSYNC();
bfin_write_USB_EP_NI0_TXMAXP(64);
SSYNC();
/* Route INTRUSB/INTR_RX/INTR_TX to USB_INT0*/
bfin_write_USB_GLOBINTR(0x7);
SSYNC();
bfin_write_USB_GLOBAL_CTL(GLOBAL_ENA | EP1_TX_ENA | EP2_TX_ENA |
EP3_TX_ENA | EP4_TX_ENA | EP5_TX_ENA |
EP6_TX_ENA | EP7_TX_ENA | EP1_RX_ENA |
EP2_RX_ENA | EP3_RX_ENA | EP4_RX_ENA |
EP5_RX_ENA | EP6_RX_ENA | EP7_RX_ENA);
SSYNC();
return 0;
}
/*
* This function performs Blackfin platform specific deinitialization for usb.
*/
void musb_platform_deinit(void)
{
}

View File

@ -0,0 +1,99 @@
/*
* Blackfin MUSB HCD (Host Controller Driver) for u-boot
*
* Copyright (c) 2008-2009 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
#ifndef __BLACKFIN_USB_H__
#define __BLACKFIN_USB_H__
#include <linux/types.h>
/* Every register is 32bit aligned, but only 16bits in size */
#define ureg(name) u16 name; u16 __pad_##name;
#define musb_regs musb_regs
struct musb_regs {
/* common registers */
ureg(faddr)
ureg(power)
ureg(intrtx)
ureg(intrrx)
ureg(intrtxe)
ureg(intrrxe)
ureg(intrusb)
ureg(intrusbe)
ureg(frame)
ureg(index)
ureg(testmode)
ureg(globintr)
ureg(global_ctl)
u32 reserved0[3];
/* indexed registers */
ureg(txmaxp)
ureg(txcsr)
ureg(rxmaxp)
ureg(rxcsr)
ureg(rxcount)
ureg(txtype)
ureg(txinterval)
ureg(rxtype)
ureg(rxinterval)
u32 reserved1;
ureg(txcount)
u32 reserved2[5];
/* fifo */
u16 fifox[32];
/* OTG, dynamic FIFO, version & vendor registers */
u32 reserved3[16];
ureg(devctl)
ureg(vbus_irq)
ureg(vbus_mask)
u32 reserved4[15];
ureg(linkinfo)
ureg(vplen)
ureg(hseof1)
ureg(fseof1)
ureg(lseof1)
u32 reserved5[41];
/* target address registers */
struct musb_tar_regs {
ureg(txmaxp)
ureg(txcsr)
ureg(rxmaxp)
ureg(rxcsr)
ureg(rxcount)
ureg(txtype)
ureg(txinternal)
ureg(rxtype)
ureg(rxinternal)
u32 reserved6;
ureg(txcount)
u32 reserved7[5];
} tar[8];
} __attribute__((packed));
struct bfin_musb_dma_regs {
ureg(interrupt);
ureg(control);
ureg(addr_low);
ureg(addr_high);
ureg(count_low);
ureg(count_high);
ureg(pad);
};
#undef ureg
/* EP5-EP7 are the only ones with 1024 byte FIFOs which BULK really needs */
#define MUSB_BULK_EP 5
/* Blackfin FIFO's are static */
#define MUSB_NO_DYNAMIC_FIFO
/* No HUB support :( */
#define MUSB_NO_MULTIPOINT
#endif

View File

@ -38,6 +38,10 @@
#include <usb_defs.h>
#include <asm/io.h>
#ifdef CONFIG_USB_BLACKFIN
# include "blackfin_usb.h"
#endif
#define MUSB_EP0_FIFOSIZE 64 /* This is non-configurable */
/* EP0 */
@ -71,6 +75,7 @@ struct musb_epN_regs {
};
/* Mentor USB core register overlay structure */
#ifndef musb_regs
struct musb_regs {
/* common registers */
u8 faddr;
@ -138,6 +143,7 @@ struct musb_regs {
} ep[16];
} __attribute__((packed, aligned(32)));
#endif
/*
* MUSB Register bits
@ -347,4 +353,14 @@ extern void musb_configure_ep(struct musb_epinfo *epinfo, u8 cnt);
extern void write_fifo(u8 ep, u32 length, void *fifo_data);
extern void read_fifo(u8 ep, u32 length, void *fifo_data);
#if defined(CONFIG_USB_BLACKFIN)
/* Every USB register is accessed as a 16-bit even if the value itself
* is only 8-bits in size. Fun stuff.
*/
# undef readb
# define readb(addr) (u8)bfin_read16(addr)
# undef writeb
# define writeb(b, addr) bfin_write16(addr, b)
#endif
#endif /* __MUSB_HDRC_DEFS_H__ */

View File

@ -38,7 +38,9 @@ extern unsigned char new[];
#define MUSB_CONTROL_EP 0
/* This defines the endpoint number used for bulk transfer */
#define MUSB_BULK_EP 1
#ifndef MUSB_BULK_EP
# define MUSB_BULK_EP 1
#endif
/* This defines the endpoint number used for interrupt transfer */
#define MUSB_INTR_EP 2

View File

@ -0,0 +1,264 @@
/*
* USB Masks
*/
#ifndef __BFIN_PERIPHERAL_USB__
#define __BFIN_PERIPHERAL_USB__
/* Bit masks for USB_FADDR */
#define FUNCTION_ADDRESS 0x7f /* Function address */
/* Bit masks for USB_POWER */
#define ENABLE_SUSPENDM 0x1 /* enable SuspendM output */
#define SUSPEND_MODE 0x2 /* Suspend Mode indicator */
#define RESUME_MODE 0x4 /* DMA Mode */
#define RESET 0x8 /* Reset indicator */
#define HS_MODE 0x10 /* High Speed mode indicator */
#define HS_ENABLE 0x20 /* high Speed Enable */
#define SOFT_CONN 0x40 /* Soft connect */
#define ISO_UPDATE 0x80 /* Isochronous update */
/* Bit masks for USB_INTRTX */
#define EP0_TX 0x1 /* Tx Endpoint 0 interrupt */
#define EP1_TX 0x2 /* Tx Endpoint 1 interrupt */
#define EP2_TX 0x4 /* Tx Endpoint 2 interrupt */
#define EP3_TX 0x8 /* Tx Endpoint 3 interrupt */
#define EP4_TX 0x10 /* Tx Endpoint 4 interrupt */
#define EP5_TX 0x20 /* Tx Endpoint 5 interrupt */
#define EP6_TX 0x40 /* Tx Endpoint 6 interrupt */
#define EP7_TX 0x80 /* Tx Endpoint 7 interrupt */
/* Bit masks for USB_INTRRX */
#define EP1_RX 0x2 /* Rx Endpoint 1 interrupt */
#define EP2_RX 0x4 /* Rx Endpoint 2 interrupt */
#define EP3_RX 0x8 /* Rx Endpoint 3 interrupt */
#define EP4_RX 0x10 /* Rx Endpoint 4 interrupt */
#define EP5_RX 0x20 /* Rx Endpoint 5 interrupt */
#define EP6_RX 0x40 /* Rx Endpoint 6 interrupt */
#define EP7_RX 0x80 /* Rx Endpoint 7 interrupt */
/* Bit masks for USB_INTRTXE */
#define EP0_TX_E 0x1 /* Endpoint 0 interrupt Enable */
#define EP1_TX_E 0x2 /* Tx Endpoint 1 interrupt enable */
#define EP2_TX_E 0x4 /* Tx Endpoint 2 interrupt enable */
#define EP3_TX_E 0x8 /* Tx Endpoint 3 interrupt enable */
#define EP4_TX_E 0x10 /* Tx Endpoint 4 interrupt enable */
#define EP5_TX_E 0x20 /* Tx Endpoint 5 interrupt enable */
#define EP6_TX_E 0x40 /* Tx Endpoint 6 interrupt enable */
#define EP7_TX_E 0x80 /* Tx Endpoint 7 interrupt enable */
/* Bit masks for USB_INTRRXE */
#define EP1_RX_E 0x02 /* Rx Endpoint 1 interrupt enable */
#define EP2_RX_E 0x04 /* Rx Endpoint 2 interrupt enable */
#define EP3_RX_E 0x08 /* Rx Endpoint 3 interrupt enable */
#define EP4_RX_E 0x10 /* Rx Endpoint 4 interrupt enable */
#define EP5_RX_E 0x20 /* Rx Endpoint 5 interrupt enable */
#define EP6_RX_E 0x40 /* Rx Endpoint 6 interrupt enable */
#define EP7_RX_E 0x80 /* Rx Endpoint 7 interrupt enable */
/* Bit masks for USB_INTRUSB */
#define SUSPEND_B 0x01 /* Suspend indicator */
#define RESUME_B 0x02 /* Resume indicator */
#define RESET_OR_BABLE_B 0x04 /* Reset/babble indicator */
#define SOF_B 0x08 /* Start of frame */
#define CONN_B 0x10 /* Connection indicator */
#define DISCON_B 0x20 /* Disconnect indicator */
#define SESSION_REQ_B 0x40 /* Session Request */
#define VBUS_ERROR_B 0x80 /* Vbus threshold indicator */
/* Bit masks for USB_INTRUSBE */
#define SUSPEND_BE 0x01 /* Suspend indicator int enable */
#define RESUME_BE 0x02 /* Resume indicator int enable */
#define RESET_OR_BABLE_BE 0x04 /* Reset/babble indicator int enable */
#define SOF_BE 0x08 /* Start of frame int enable */
#define CONN_BE 0x10 /* Connection indicator int enable */
#define DISCON_BE 0x20 /* Disconnect indicator int enable */
#define SESSION_REQ_BE 0x40 /* Session Request int enable */
#define VBUS_ERROR_BE 0x80 /* Vbus threshold indicator int enable */
/* Bit masks for USB_FRAME */
#define FRAME_NUMBER 0x7ff /* Frame number */
/* Bit masks for USB_INDEX */
#define SELECTED_ENDPOINT 0xf /* selected endpoint */
/* Bit masks for USB_GLOBAL_CTL */
#define GLOBAL_ENA 0x0001 /* enables USB module */
#define EP1_TX_ENA 0x0002 /* Transmit endpoint 1 enable */
#define EP2_TX_ENA 0x0004 /* Transmit endpoint 2 enable */
#define EP3_TX_ENA 0x0008 /* Transmit endpoint 3 enable */
#define EP4_TX_ENA 0x0010 /* Transmit endpoint 4 enable */
#define EP5_TX_ENA 0x0020 /* Transmit endpoint 5 enable */
#define EP6_TX_ENA 0x0040 /* Transmit endpoint 6 enable */
#define EP7_TX_ENA 0x0080 /* Transmit endpoint 7 enable */
#define EP1_RX_ENA 0x0100 /* Receive endpoint 1 enable */
#define EP2_RX_ENA 0x0200 /* Receive endpoint 2 enable */
#define EP3_RX_ENA 0x0400 /* Receive endpoint 3 enable */
#define EP4_RX_ENA 0x0800 /* Receive endpoint 4 enable */
#define EP5_RX_ENA 0x1000 /* Receive endpoint 5 enable */
#define EP6_RX_ENA 0x2000 /* Receive endpoint 6 enable */
#define EP7_RX_ENA 0x4000 /* Receive endpoint 7 enable */
/* Bit masks for USB_OTG_DEV_CTL */
#define SESSION 0x1 /* session indicator */
#define HOST_REQ 0x2 /* Host negotiation request */
#define HOST_MODE 0x4 /* indicates USBDRC is a host */
#define VBUS0 0x8 /* Vbus level indicator[0] */
#define VBUS1 0x10 /* Vbus level indicator[1] */
#define LSDEV 0x20 /* Low-speed indicator */
#define FSDEV 0x40 /* Full or High-speed indicator */
#define B_DEVICE 0x80 /* A' or 'B' device indicator */
/* Bit masks for USB_OTG_VBUS_IRQ */
#define DRIVE_VBUS_ON 0x1 /* indicator to drive VBUS control circuit */
#define DRIVE_VBUS_OFF 0x2 /* indicator to shut off charge pump */
#define CHRG_VBUS_START 0x4 /* indicator for external circuit to start charging VBUS */
#define CHRG_VBUS_END 0x8 /* indicator for external circuit to end charging VBUS */
#define DISCHRG_VBUS_START 0x10 /* indicator to start discharging VBUS */
#define DISCHRG_VBUS_END 0x20 /* indicator to stop discharging VBUS */
/* Bit masks for USB_OTG_VBUS_MASK */
#define DRIVE_VBUS_ON_ENA 0x01 /* enable DRIVE_VBUS_ON interrupt */
#define DRIVE_VBUS_OFF_ENA 0x02 /* enable DRIVE_VBUS_OFF interrupt */
#define CHRG_VBUS_START_ENA 0x04 /* enable CHRG_VBUS_START interrupt */
#define CHRG_VBUS_END_ENA 0x08 /* enable CHRG_VBUS_END interrupt */
#define DISCHRG_VBUS_START_ENA 0x10 /* enable DISCHRG_VBUS_START interrupt */
#define DISCHRG_VBUS_END_ENA 0x20 /* enable DISCHRG_VBUS_END interrupt */
/* Bit masks for USB_CSR0 */
#define RXPKTRDY 0x1 /* data packet receive indicator */
#define TXPKTRDY 0x2 /* data packet in FIFO indicator */
#define STALL_SENT 0x4 /* STALL handshake sent */
#define DATAEND 0x8 /* Data end indicator */
#define SETUPEND 0x10 /* Setup end */
#define SENDSTALL 0x20 /* Send STALL handshake */
#define SERVICED_RXPKTRDY 0x40 /* used to clear the RxPktRdy bit */
#define SERVICED_SETUPEND 0x80 /* used to clear the SetupEnd bit */
#define FLUSHFIFO 0x100 /* flush endpoint FIFO */
#define STALL_RECEIVED_H 0x4 /* STALL handshake received host mode */
#define SETUPPKT_H 0x8 /* send Setup token host mode */
#define ERROR_H 0x10 /* timeout error indicator host mode */
#define REQPKT_H 0x20 /* Request an IN transaction host mode */
#define STATUSPKT_H 0x40 /* Status stage transaction host mode */
#define NAK_TIMEOUT_H 0x80 /* EP0 halted after a NAK host mode */
/* Bit masks for USB_COUNT0 */
#define EP0_RX_COUNT 0x7f /* number of received bytes in EP0 FIFO */
/* Bit masks for USB_NAKLIMIT0 */
#define EP0_NAK_LIMIT 0x1f /* frames/micro frames count after which EP0 timeouts */
/* Bit masks for USB_TX_MAX_PACKET */
#define MAX_PACKET_SIZE_T 0x7ff /* maximum data pay load in a frame */
/* Bit masks for USB_RX_MAX_PACKET */
#define MAX_PACKET_SIZE_R 0x7ff /* maximum data pay load in a frame */
/* Bit masks for USB_TXCSR */
#define TXPKTRDY_T 0x1 /* data packet in FIFO indicator */
#define FIFO_NOT_EMPTY_T 0x2 /* FIFO not empty */
#define UNDERRUN_T 0x4 /* TxPktRdy not set for an IN token */
#define FLUSHFIFO_T 0x8 /* flush endpoint FIFO */
#define STALL_SEND_T 0x10 /* issue a Stall handshake */
#define STALL_SENT_T 0x20 /* Stall handshake transmitted */
#define CLEAR_DATATOGGLE_T 0x40 /* clear endpoint data toggle */
#define INCOMPTX_T 0x80 /* indicates that a large packet is split */
#define DMAREQMODE_T 0x400 /* DMA mode (0 or 1) selection */
#define FORCE_DATATOGGLE_T 0x800 /* Force data toggle */
#define DMAREQ_ENA_T 0x1000 /* Enable DMA request for Tx EP */
#define ISO_T 0x4000 /* enable Isochronous transfers */
#define AUTOSET_T 0x8000 /* allows TxPktRdy to be set automatically */
#define ERROR_TH 0x4 /* error condition host mode */
#define STALL_RECEIVED_TH 0x20 /* Stall handshake received host mode */
#define NAK_TIMEOUT_TH 0x80 /* NAK timeout host mode */
/* Bit masks for USB_TXCOUNT */
#define TX_COUNT 0x1fff /* Byte len for the selected endpoint Tx FIFO */
/* Bit masks for USB_RXCSR */
#define RXPKTRDY_R 0x1 /* data packet in FIFO indicator */
#define FIFO_FULL_R 0x2 /* FIFO not empty */
#define OVERRUN_R 0x4 /* TxPktRdy not set for an IN token */
#define DATAERROR_R 0x8 /* Out packet cannot be loaded into Rx FIFO */
#define FLUSHFIFO_R 0x10 /* flush endpoint FIFO */
#define STALL_SEND_R 0x20 /* issue a Stall handshake */
#define STALL_SENT_R 0x40 /* Stall handshake transmitted */
#define CLEAR_DATATOGGLE_R 0x80 /* clear endpoint data toggle */
#define INCOMPRX_R 0x100 /* indicates that a large packet is split */
#define DMAREQMODE_R 0x800 /* DMA mode (0 or 1) selection */
#define DISNYET_R 0x1000 /* disable Nyet handshakes */
#define DMAREQ_ENA_R 0x2000 /* Enable DMA request for Tx EP */
#define ISO_R 0x4000 /* enable Isochronous transfers */
#define AUTOCLEAR_R 0x8000 /* allows TxPktRdy to be set automatically */
#define ERROR_RH 0x4 /* TxPktRdy not set for an IN token host mode */
#define REQPKT_RH 0x20 /* request an IN transaction host mode */
#define STALL_RECEIVED_RH 0x40 /* Stall handshake received host mode */
#define INCOMPRX_RH 0x100 /* large packet is split host mode */
#define DMAREQMODE_RH 0x800 /* DMA mode (0 or 1) selection host mode */
#define AUTOREQ_RH 0x4000 /* sets ReqPkt automatically host mode */
/* Bit masks for USB_RXCOUNT */
#define RX_COUNT 0x1fff /* Packet byte len in the Rx FIFO */
/* Bit masks for USB_TXTYPE */
#define TARGET_EP_NO_T 0xf /* EP number */
#define PROTOCOL_T 0xc /* transfer type */
/* Bit masks for USB_TXINTERVAL */
#define TX_POLL_INTERVAL 0xff /* polling interval for selected Tx EP */
/* Bit masks for USB_RXTYPE */
#define TARGET_EP_NO_R 0xf /* EP number */
#define PROTOCOL_R 0xc /* transfer type */
/* Bit masks for USB_RXINTERVAL */
#define RX_POLL_INTERVAL 0xff /* polling interval for selected Rx EP */
/* Bit masks for USB_DMA_INTERRUPT */
#define DMA0_INT 0x1 /* DMA0 pending interrupt */
#define DMA1_INT 0x2 /* DMA1 pending interrupt */
#define DMA2_INT 0x4 /* DMA2 pending interrupt */
#define DMA3_INT 0x8 /* DMA3 pending interrupt */
#define DMA4_INT 0x10 /* DMA4 pending interrupt */
#define DMA5_INT 0x20 /* DMA5 pending interrupt */
#define DMA6_INT 0x40 /* DMA6 pending interrupt */
#define DMA7_INT 0x80 /* DMA7 pending interrupt */
/* Bit masks for USB_DMAxCONTROL */
#define DMA_ENA 0x1 /* DMA enable */
#define DIRECTION 0x2 /* direction of DMA transfer */
#define MODE 0x4 /* DMA Bus error */
#define INT_ENA 0x8 /* Interrupt enable */
#define EPNUM 0xf0 /* EP number */
#define BUSERROR 0x100 /* DMA Bus error */
#endif

View File

@ -132,7 +132,8 @@ struct usb_device {
defined(CONFIG_USB_EHCI) || defined(CONFIG_USB_OHCI_NEW) || \
defined(CONFIG_USB_SL811HS) || defined(CONFIG_USB_ISP116X_HCD) || \
defined(CONFIG_USB_R8A66597_HCD) || defined(CONFIG_USB_DAVINCI) || \
defined(CONFIG_USB_OMAP3) || defined(CONFIG_USB_DA8XX)
defined(CONFIG_USB_OMAP3) || defined(CONFIG_USB_DA8XX) || \
defined(CONFIG_USB_BLACKFIN)
int usb_lowlevel_init(void);
int usb_lowlevel_stop(void);