mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-10-30 19:48:19 +00:00 
			
		
		
		
	Signed-off-by: Francesco Rendine <francesco.rendine@valueteam.com> Signed-off-by: Damien Dusha <d.dusha@gmail.com> Signed-off-by: Anatolij Gustschin <agust@denx.de> Coding style cleanup; slight file restructuring. Signed-off-by: Wolfgang Denk <wd@denx.de> Acked-by: Remy Bohmer <linux@bohmer.net>
		
			
				
	
	
		
			160 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			160 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * (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
 | |
|  *
 | |
|  * 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 <pci.h>
 | |
| #include <usb.h>
 | |
| #include <asm/io.h>
 | |
| #include <usb/ehci-fsl.h>
 | |
| 
 | |
| #include "ehci.h"
 | |
| #include "ehci-core.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(void)
 | |
| {
 | |
| 	volatile struct usb_ehci *ehci;
 | |
| 
 | |
| 	/* Hook the memory mapped registers for EHCI-Controller */
 | |
| 	ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB_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(void)
 | |
| {
 | |
| 	volatile struct usb_ehci *ehci;
 | |
| 	int exit_status = 0;
 | |
| 
 | |
| 	if (hcor) {
 | |
| 		/* Unhook struct */
 | |
| 		hccr = NULL;
 | |
| 		hcor = NULL;
 | |
| 
 | |
| 		/* Reset the USB controller */
 | |
| 		ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB_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 );
 | |
| }
 |