/* * Blackfin MUSB HCD (Host Controller Driver) for u-boot * * Copyright (c) 2008-2009 Analog Devices Inc. * * Licensed under the GPL-2 or later. */ #include #include #include #include #include #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) { }