diff options
Diffstat (limited to 'board/micronas/vct/ehci.c')
-rw-r--r-- | board/micronas/vct/ehci.c | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/board/micronas/vct/ehci.c b/board/micronas/vct/ehci.c new file mode 100644 index 0000000000..d04bdceac9 --- /dev/null +++ b/board/micronas/vct/ehci.c @@ -0,0 +1,110 @@ +/* + * (C) Copyright 2009 Stefan Roese <sr@denx.de>, DENX Software Engineering + * + * Original Author Guenter Gebhardt + * Copyright (C) 2006 Micronas GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +#include "vct.h" + +int vct_ehci_hcd_init(u32 *hccr, u32 *hcor) +{ + int retval; + u32 val; + u32 addr; + + dcgu_set_reset_switch(DCGU_HW_MODULE_USB_24, DCGU_SWITCH_ON); + dcgu_set_reset_switch(DCGU_HW_MODULE_USB_60, DCGU_SWITCH_ON); + dcgu_set_clk_switch(DCGU_HW_MODULE_USB_24, DCGU_SWITCH_ON); + dcgu_set_clk_switch(DCGU_HW_MODULE_USB_PLL, DCGU_SWITCH_ON); + dcgu_set_reset_switch(DCGU_HW_MODULE_USB_24, DCGU_SWITCH_OFF); + + /* Wait until (DCGU_USBPHY_STAT == 7) */ + addr = DCGU_USBPHY_STAT(DCGU_BASE); + val = reg_read(addr); + while (val != 7) + val = reg_read(addr); + + dcgu_set_clk_switch(DCGU_HW_MODULE_USB_60, DCGU_SWITCH_ON); + dcgu_set_reset_switch(DCGU_HW_MODULE_USB_60, DCGU_SWITCH_OFF); + + retval = scc_reset(SCC_USB_RW, 0); + if (retval) { + printf("scc_reset(SCC_USB_RW, 0) returned: 0x%x\n", retval); + return retval; + } else { + retval = scc_reset(SCC_CPU1_SPDMA_RW, 0); + if (retval) { + printf("scc_reset(SCC_CPU1_SPDMA_RW, 0) returned: 0x%x\n", + retval); + return retval; + } + } + + if (!retval) { + /* + * For the AGU bypass, where the SCC client provides full + * physical address + */ + scc_set_usb_address_generation_mode(1); + scc_setup_dma(SCC_USB_RW, BCU_USB_BUFFER_1, DMA_LINEAR, + USE_NO_FH, DMA_READ, 0); + scc_setup_dma(SCC_CPU1_SPDMA_RW, BCU_USB_BUFFER_1, DMA_LINEAR, + USE_NO_FH, DMA_WRITE, 0); + scc_setup_dma(SCC_USB_RW, BCU_USB_BUFFER_0, DMA_LINEAR, + USE_NO_FH, DMA_WRITE, 0); + scc_setup_dma(SCC_CPU1_SPDMA_RW, BCU_USB_BUFFER_0, DMA_LINEAR, + USE_NO_FH, DMA_READ, 0); + + /* Enable memory interface */ + scc_enable(SCC_USB_RW, 1); + + /* Start (start_cmd=0) DMAs */ + scc_dma_cmd(SCC_USB_RW, DMA_START, 0, DMA_READ); + scc_dma_cmd(SCC_USB_RW, DMA_START, 0, DMA_WRITE); + } else { + printf("Cannot configure USB memory channel.\n"); + printf("USB can not access RAM. SCC configuration failed.\n"); + return retval; + } + + /* Wait a short while */ + udelay(300000); + + reg_write(USBH_BURSTSIZE(USBH_BASE), 0x00001c1c); + + /* Set EHCI structures and DATA in RAM */ + reg_write(USBH_USBHMISC(USBH_BASE), 0x00840003); + /* Set USBMODE to bigendian and set host mode */ + reg_write(USBH_USBMODE(USBH_BASE), 0x00000007); + + /* + * USBH_BURSTSIZE MUST EQUAL 0x00001c1c in order for + * 512 byte USB transfers on the bulk pipe to work properly. + * Set USBH_BURSTSIZE to 0x00001c1c + */ + reg_write(USBH_BURSTSIZE(USBH_BASE), 0x00001c1c); + + /* Insert access register addresses */ + *hccr = REG_GLOBAL_START_ADDR + USBH_CAPLENGTH(USBH_BASE); + *hcor = REG_GLOBAL_START_ADDR + USBH_USBCMD(USBH_BASE); + + return 0; +} |