diff options
author | Bryan Wu <bryan.wu@analog.com> | 2009-12-16 22:04:02 -0500 |
---|---|---|
committer | Remy Bohmer <linux@bohmer.net> | 2010-01-09 10:25:09 +0100 |
commit | e608f221c13943d88e86f44753e23668342c3df3 (patch) | |
tree | 1f1aaa9edfc854e119151ba91398afc98e09cf62 /drivers | |
parent | bc72a919e037782f64e3ac45c91bc60408e57e85 (diff) |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/musb/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/musb/blackfin_usb.c | 143 | ||||
-rw-r--r-- | drivers/usb/musb/blackfin_usb.h | 99 | ||||
-rw-r--r-- | drivers/usb/musb/musb_core.h | 16 | ||||
-rw-r--r-- | drivers/usb/musb/musb_hcd.h | 4 |
5 files changed, 262 insertions, 1 deletions
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile index 12e115ef11..397f5fe7a3 100644 --- a/drivers/usb/musb/Makefile +++ b/drivers/usb/musb/Makefile @@ -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 diff --git a/drivers/usb/musb/blackfin_usb.c b/drivers/usb/musb/blackfin_usb.c new file mode 100644 index 0000000000..38aceb2e93 --- /dev/null +++ b/drivers/usb/musb/blackfin_usb.c @@ -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(®s->addr_low, val); + SSYNC(); + + bfin_write16(®s->addr_high, val >> 16); + SSYNC(); + + /* Setup DMA count register */ + bfin_write16(®s->count_low, length); + bfin_write16(®s->count_high, 0); + SSYNC(); + + /* Enable the DMA */ + val = (ep << 4) | DMA_ENA | INT_ENA; + if (is_write) + val |= DIRECTION; + bfin_write16(®s->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(®s->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) +{ +} diff --git a/drivers/usb/musb/blackfin_usb.h b/drivers/usb/musb/blackfin_usb.h new file mode 100644 index 0000000000..ab26ca2d51 --- /dev/null +++ b/drivers/usb/musb/blackfin_usb.h @@ -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 diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index cee7a11294..f0f0301bd1 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -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__ */ diff --git a/drivers/usb/musb/musb_hcd.h b/drivers/usb/musb/musb_hcd.h index 17e9091a0a..a437985dc8 100644 --- a/drivers/usb/musb/musb_hcd.h +++ b/drivers/usb/musb/musb_hcd.h @@ -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 |