|
|
|
/*
|
|
|
|
* 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/clock.h>
|
|
|
|
#include <asm/mach-common/bits/usb.h>
|
|
|
|
|
|
|
|
#include "musb_core.h"
|
|
|
|
|
|
|
|
#ifndef CONFIG_USB_BLACKFIN_CLKIN
|
|
|
|
#define CONFIG_USB_BLACKFIN_CLKIN 24
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* 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")));
|
|
|
|
|
|
|
|
static void bfin_anomaly_init(void)
|
|
|
|
{
|
|
|
|
u32 revid;
|
|
|
|
|
|
|
|
if (!ANOMALY_05000346 && !ANOMALY_05000347)
|
|
|
|
return;
|
|
|
|
|
|
|
|
revid = bfin_revid();
|
|
|
|
|
|
|
|
#ifdef __ADSPBF54x__
|
|
|
|
if (revid > 0)
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
#ifdef __ADSPBF52x__
|
|
|
|
if (ANOMALY_BF526 && revid > 0)
|
|
|
|
return;
|
|
|
|
if (ANOMALY_BF527 && revid > 1)
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (ANOMALY_05000346) {
|
|
|
|
bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value);
|
|
|
|
SSYNC();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ANOMALY_05000347) {
|
|
|
|
bfin_write_USB_APHY_CNTRL(0x0);
|
|
|
|
SSYNC();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int musb_platform_init(void)
|
|
|
|
{
|
|
|
|
/* board specific initialization */
|
|
|
|
board_musb_init();
|
|
|
|
|
|
|
|
bfin_anomaly_init();
|
|
|
|
|
|
|
|
/* Configure PLL oscillator register */
|
|
|
|
bfin_write_USB_PLLOSC_CTRL(0x3080 |
|
|
|
|
((480 / CONFIG_USB_BLACKFIN_CLKIN) << 1));
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
}
|