12731b9a8SJean-Christophe PLAGNIOL-VILLARD /* 21b719e66SRamneek Mehresh * (C) Copyright 2009, 2011 Freescale Semiconductor, Inc. 34ef01010SVivek Mahajan * 42731b9a8SJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2008, Excito Elektronik i Sk=E5ne AB 52731b9a8SJean-Christophe PLAGNIOL-VILLARD * 62731b9a8SJean-Christophe PLAGNIOL-VILLARD * Author: Tor Krill tor@excito.com 72731b9a8SJean-Christophe PLAGNIOL-VILLARD * 81a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 92731b9a8SJean-Christophe PLAGNIOL-VILLARD */ 102731b9a8SJean-Christophe PLAGNIOL-VILLARD 112731b9a8SJean-Christophe PLAGNIOL-VILLARD #include <common.h> 122731b9a8SJean-Christophe PLAGNIOL-VILLARD #include <pci.h> 132731b9a8SJean-Christophe PLAGNIOL-VILLARD #include <usb.h> 142731b9a8SJean-Christophe PLAGNIOL-VILLARD #include <asm/io.h> 154ef01010SVivek Mahajan #include <usb/ehci-fsl.h> 161b719e66SRamneek Mehresh #include <hwconfig.h> 172731b9a8SJean-Christophe PLAGNIOL-VILLARD 182731b9a8SJean-Christophe PLAGNIOL-VILLARD #include "ehci.h" 192731b9a8SJean-Christophe PLAGNIOL-VILLARD 20047cea36SShengzhou Liu /* Check USB PHY clock valid */ 21047cea36SShengzhou Liu static int usb_phy_clk_valid(struct usb_ehci *ehci) 22047cea36SShengzhou Liu { 23047cea36SShengzhou Liu if (!((in_be32(&ehci->control) & PHY_CLK_VALID) || 24047cea36SShengzhou Liu in_be32(&ehci->prictrl))) { 25047cea36SShengzhou Liu printf("USB PHY clock invalid!\n"); 26047cea36SShengzhou Liu return 0; 27047cea36SShengzhou Liu } else { 28047cea36SShengzhou Liu return 1; 29047cea36SShengzhou Liu } 30047cea36SShengzhou Liu } 31047cea36SShengzhou Liu 322731b9a8SJean-Christophe PLAGNIOL-VILLARD /* 332731b9a8SJean-Christophe PLAGNIOL-VILLARD * Create the appropriate control structures to manage 342731b9a8SJean-Christophe PLAGNIOL-VILLARD * a new EHCI host controller. 352731b9a8SJean-Christophe PLAGNIOL-VILLARD * 362731b9a8SJean-Christophe PLAGNIOL-VILLARD * Excerpts from linux ehci fsl driver. 372731b9a8SJean-Christophe PLAGNIOL-VILLARD */ 38127efc4fSTroy Kisky int ehci_hcd_init(int index, enum usb_init_type init, 39127efc4fSTroy Kisky struct ehci_hccr **hccr, struct ehci_hcor **hcor) 402731b9a8SJean-Christophe PLAGNIOL-VILLARD { 4177354e9dSramneek mehresh struct usb_ehci *ehci = NULL; 421b719e66SRamneek Mehresh const char *phy_type = NULL; 431b719e66SRamneek Mehresh size_t len; 44*0ecb15c8SNikhil Badola char current_usb_controller[5]; 45dd22f7cfSKumar Gala #ifdef CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY 46dd22f7cfSKumar Gala char usb_phy[5]; 471b719e66SRamneek Mehresh 481b719e66SRamneek Mehresh usb_phy[0] = '\0'; 49dd22f7cfSKumar Gala #endif 50*0ecb15c8SNikhil Badola memset(current_usb_controller, '\0', 5); 51*0ecb15c8SNikhil Badola snprintf(current_usb_controller, 4, "usb%d", index+1); 522731b9a8SJean-Christophe PLAGNIOL-VILLARD 5377354e9dSramneek mehresh switch (index) { 5477354e9dSramneek mehresh case 0: 5577354e9dSramneek mehresh ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB1_ADDR; 5677354e9dSramneek mehresh break; 5777354e9dSramneek mehresh case 1: 5877354e9dSramneek mehresh ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB2_ADDR; 5977354e9dSramneek mehresh break; 6077354e9dSramneek mehresh default: 6177354e9dSramneek mehresh printf("ERROR: wrong controller index!!\n"); 6277354e9dSramneek mehresh break; 6377354e9dSramneek mehresh }; 6477354e9dSramneek mehresh 65676ae068SLucas Stach *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); 66676ae068SLucas Stach *hcor = (struct ehci_hcor *)((uint32_t) *hccr + 67676ae068SLucas Stach HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); 682731b9a8SJean-Christophe PLAGNIOL-VILLARD 692731b9a8SJean-Christophe PLAGNIOL-VILLARD /* Set to Host mode */ 7008066152SVivek Mahajan setbits_le32(&ehci->usbmode, CM_HOST); 712731b9a8SJean-Christophe PLAGNIOL-VILLARD 7208066152SVivek Mahajan out_be32(&ehci->snoop1, SNOOP_SIZE_2GB); 7308066152SVivek Mahajan out_be32(&ehci->snoop2, 0x80000000 | SNOOP_SIZE_2GB); 742731b9a8SJean-Christophe PLAGNIOL-VILLARD 752731b9a8SJean-Christophe PLAGNIOL-VILLARD /* Init phy */ 76*0ecb15c8SNikhil Badola if (hwconfig_sub(current_usb_controller, "phy_type")) 77*0ecb15c8SNikhil Badola phy_type = hwconfig_subarg(current_usb_controller, 78*0ecb15c8SNikhil Badola "phy_type", &len); 794ef01010SVivek Mahajan else 801b719e66SRamneek Mehresh phy_type = getenv("usb_phy_type"); 811b719e66SRamneek Mehresh 821b719e66SRamneek Mehresh if (!phy_type) { 831b719e66SRamneek Mehresh #ifdef CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY 841b719e66SRamneek Mehresh /* if none specified assume internal UTMI */ 851b719e66SRamneek Mehresh strcpy(usb_phy, "utmi"); 861b719e66SRamneek Mehresh phy_type = usb_phy; 871b719e66SRamneek Mehresh #else 881b719e66SRamneek Mehresh printf("WARNING: USB phy type not defined !!\n"); 891b719e66SRamneek Mehresh return -1; 901b719e66SRamneek Mehresh #endif 911b719e66SRamneek Mehresh } 921b719e66SRamneek Mehresh 9391d7746dSNikhil Badola if (!strncmp(phy_type, "utmi", 4)) { 941b719e66SRamneek Mehresh #if defined(CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY) 951b719e66SRamneek Mehresh setbits_be32(&ehci->control, PHY_CLK_SEL_UTMI); 961b719e66SRamneek Mehresh setbits_be32(&ehci->control, UTMI_PHY_EN); 971b719e66SRamneek Mehresh udelay(1000); /* delay required for PHY Clk to appear */ 981b719e66SRamneek Mehresh #endif 99676ae068SLucas Stach out_le32(&(*hcor)->or_portsc[0], PORT_PTS_UTMI); 100047cea36SShengzhou Liu setbits_be32(&ehci->control, USB_EN); 1011b719e66SRamneek Mehresh } else { 1021b719e66SRamneek Mehresh setbits_be32(&ehci->control, PHY_CLK_SEL_ULPI); 103047cea36SShengzhou Liu clrsetbits_be32(&ehci->control, UTMI_PHY_EN, USB_EN); 1041b719e66SRamneek Mehresh udelay(1000); /* delay required for PHY Clk to appear */ 105047cea36SShengzhou Liu if (!usb_phy_clk_valid(ehci)) 106047cea36SShengzhou Liu return -EINVAL; 107676ae068SLucas Stach out_le32(&(*hcor)->or_portsc[0], PORT_PTS_ULPI); 1081b719e66SRamneek Mehresh } 1092731b9a8SJean-Christophe PLAGNIOL-VILLARD 11008066152SVivek Mahajan out_be32(&ehci->prictrl, 0x0000000c); 11108066152SVivek Mahajan out_be32(&ehci->age_cnt_limit, 0x00000040); 11208066152SVivek Mahajan out_be32(&ehci->sictrl, 0x00000001); 1132731b9a8SJean-Christophe PLAGNIOL-VILLARD 11408066152SVivek Mahajan in_le32(&ehci->usbmode); 1152731b9a8SJean-Christophe PLAGNIOL-VILLARD 1162731b9a8SJean-Christophe PLAGNIOL-VILLARD return 0; 1172731b9a8SJean-Christophe PLAGNIOL-VILLARD } 1182731b9a8SJean-Christophe PLAGNIOL-VILLARD 1192731b9a8SJean-Christophe PLAGNIOL-VILLARD /* 1202731b9a8SJean-Christophe PLAGNIOL-VILLARD * Destroy the appropriate control structures corresponding 1212731b9a8SJean-Christophe PLAGNIOL-VILLARD * the the EHCI host controller. 1222731b9a8SJean-Christophe PLAGNIOL-VILLARD */ 123676ae068SLucas Stach int ehci_hcd_stop(int index) 1242731b9a8SJean-Christophe PLAGNIOL-VILLARD { 1252731b9a8SJean-Christophe PLAGNIOL-VILLARD return 0; 1262731b9a8SJean-Christophe PLAGNIOL-VILLARD } 127