diff options
Diffstat (limited to 'qemu/roms/u-boot/drivers/usb/host/ehci-mpc512x.c')
-rw-r--r-- | qemu/roms/u-boot/drivers/usb/host/ehci-mpc512x.c | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/qemu/roms/u-boot/drivers/usb/host/ehci-mpc512x.c b/qemu/roms/u-boot/drivers/usb/host/ehci-mpc512x.c new file mode 100644 index 000000000..b320c4a4e --- /dev/null +++ b/qemu/roms/u-boot/drivers/usb/host/ehci-mpc512x.c @@ -0,0 +1,140 @@ +/* + * (C) Copyright 2010, Damien Dusha, <d.dusha@gmail.com> + * + * (C) Copyright 2009, Value Team S.p.A. + * Francesco Rendine, <francesco.rendine@valueteam.com> + * + * (C) Copyright 2009 Freescale Semiconductor, Inc. + * + * (C) Copyright 2008, Excito Elektronik i Sk=E5ne AB + * + * Author: Tor Krill tor@excito.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <pci.h> +#include <usb.h> +#include <asm/io.h> +#include <usb/ehci-fsl.h> + +#include "ehci.h" + +static void fsl_setup_phy(volatile struct ehci_hcor *); +static void fsl_platform_set_host_mode(volatile struct usb_ehci *ehci); +static int reset_usb_controller(volatile struct usb_ehci *ehci); +static void usb_platform_dr_init(volatile struct usb_ehci *ehci); + +/* + * Initialize SOC FSL EHCI Controller + * + * This code is derived from EHCI FSL USB Linux driver for MPC5121 + * + */ +int ehci_hcd_init(int index, enum usb_init_type init, + struct ehci_hccr **hccr, struct ehci_hcor **hcor) +{ + volatile struct usb_ehci *ehci; + + /* Hook the memory mapped registers for EHCI-Controller */ + ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB1_ADDR; + *hccr = (struct ehci_hccr *)((uint32_t)&(ehci->caplength)); + *hcor = (struct ehci_hcor *)((uint32_t) *hccr + + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); + + /* configure interface for UTMI_WIDE */ + usb_platform_dr_init(ehci); + + /* Init Phy USB0 to UTMI+ */ + fsl_setup_phy(*hcor); + + /* Set to host mode */ + fsl_platform_set_host_mode(ehci); + + /* + * Setting the burst size seems to be required to prevent the + * USB from hanging when communicating with certain USB Mass + * storage devices. This was determined by analysing the + * EHCI registers under Linux vs U-Boot and burstsize was the + * major non-interrupt related difference between the two + * implementations. + * + * Some USB sticks behave better than others. In particular, + * the following USB stick is especially problematic: + * 0930:6545 Toshiba Corp + * + * The burstsize is set here to match the Linux implementation. + */ + out_be32(&ehci->burstsize, FSL_EHCI_TXPBURST(8) | + FSL_EHCI_RXPBURST(8)); + + return 0; +} + +/* + * Destroy the appropriate control structures corresponding + * the the EHCI host controller. + */ +int ehci_hcd_stop(int index) +{ + volatile struct usb_ehci *ehci; + int exit_status = 0; + + /* Reset the USB controller */ + ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB1_ADDR; + exit_status = reset_usb_controller(ehci); + + return exit_status; +} + +static int reset_usb_controller(volatile struct usb_ehci *ehci) +{ + unsigned int i; + + /* Command a reset of the USB Controller */ + out_be32(&(ehci->usbcmd), EHCI_FSL_USBCMD_RST); + + /* Wait for the reset process to finish */ + for (i = 65535 ; i > 0 ; i--) { + /* + * The host will set this bit to zero once the + * reset process is complete + */ + if ((in_be32(&(ehci->usbcmd)) & EHCI_FSL_USBCMD_RST) == 0) + return 0; + } + + /* Hub did not reset in time */ + return -1; +} + +static void fsl_setup_phy(volatile struct ehci_hcor *hcor) +{ + uint32_t portsc; + + portsc = ehci_readl(&hcor->or_portsc[0]); + portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW); + + /* Enable the phy mode to UTMI Wide */ + portsc |= PORT_PTS_PTW; + portsc |= PORT_PTS_UTMI; + + ehci_writel(&hcor->or_portsc[0], portsc); +} + +static void fsl_platform_set_host_mode(volatile struct usb_ehci *ehci) +{ + uint32_t temp; + + temp = in_le32(&ehci->usbmode); + temp |= CM_HOST | ES_BE; + out_le32(&ehci->usbmode, temp); +} + +static void usb_platform_dr_init(volatile struct usb_ehci *ehci) +{ + /* Configure interface for UTMI_WIDE */ + out_be32(&ehci->isiphyctrl, PHYCTRL_PHYE | PHYCTRL_PXE); + out_be32(&ehci->usbgenctrl, GC_PPP | GC_PFP ); +} |