mirror of
				https://source.denx.de/u-boot/u-boot.git
				synced 2025-11-03 01:41:44 +01:00 
			
		
		
		
	Use definitions from ehci.h instead. Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com> Acked-by: Marek Vasut <marex@denx.de> Tested-by: Simon Glass <sjg@chromium.org>
		
			
				
	
	
		
			141 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			141 lines
		
	
	
		
			3.5 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
 | 
						|
 *
 | 
						|
 * SPDX-License-Identifier:	GPL-2.0+
 | 
						|
 */
 | 
						|
 | 
						|
#include <common.h>
 | 
						|
#include <pci.h>
 | 
						|
#include <usb.h>
 | 
						|
#include <asm/io.h>
 | 
						|
#include <usb/ehci-ci.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), CMD_RESET);
 | 
						|
 | 
						|
	/* 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)) & CMD_RESET) == 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 );
 | 
						|
}
 |