15b591502SStefano Babic /* 25b591502SStefano Babic * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> 35b591502SStefano Babic * 41a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 55b591502SStefano Babic */ 65b591502SStefano Babic 75b591502SStefano Babic 85b591502SStefano Babic #include <common.h> 95b591502SStefano Babic #include <usb.h> 105b591502SStefano Babic #include <asm/io.h> 1186271115SStefano Babic #include <asm/arch/imx-regs.h> 125b591502SStefano Babic #include <usb/ehci-fsl.h> 135b591502SStefano Babic #include <errno.h> 145b591502SStefano Babic 155b591502SStefano Babic #include "ehci.h" 165b591502SStefano Babic 175b591502SStefano Babic #define USBCTRL_OTGBASE_OFFSET 0x600 185b591502SStefano Babic 199fa3d093SBenoît Thébaudeau #define MX25_OTG_SIC_SHIFT 29 209fa3d093SBenoît Thébaudeau #define MX25_OTG_SIC_MASK (0x3 << MX25_OTG_SIC_SHIFT) 219fa3d093SBenoît Thébaudeau #define MX25_OTG_PM_BIT (1 << 24) 229fa3d093SBenoît Thébaudeau #define MX25_OTG_PP_BIT (1 << 11) 239fa3d093SBenoît Thébaudeau #define MX25_OTG_OCPOL_BIT (1 << 3) 249fa3d093SBenoît Thébaudeau 259fa3d093SBenoît Thébaudeau #define MX25_H1_SIC_SHIFT 21 269fa3d093SBenoît Thébaudeau #define MX25_H1_SIC_MASK (0x3 << MX25_H1_SIC_SHIFT) 279fa3d093SBenoît Thébaudeau #define MX25_H1_PP_BIT (1 << 18) 28fa88ddb7SBenoît Thébaudeau #define MX25_H1_PM_BIT (1 << 16) 299fa3d093SBenoît Thébaudeau #define MX25_H1_IPPUE_UP_BIT (1 << 7) 309fa3d093SBenoît Thébaudeau #define MX25_H1_IPPUE_DOWN_BIT (1 << 6) 319fa3d093SBenoît Thébaudeau #define MX25_H1_TLL_BIT (1 << 5) 329fa3d093SBenoît Thébaudeau #define MX25_H1_USBTE_BIT (1 << 4) 339fa3d093SBenoît Thébaudeau #define MX25_H1_OCPOL_BIT (1 << 2) 34dddb7c9fSMatthias Weisser 355b591502SStefano Babic #define MX31_OTG_SIC_SHIFT 29 365b591502SStefano Babic #define MX31_OTG_SIC_MASK (0x3 << MX31_OTG_SIC_SHIFT) 375b591502SStefano Babic #define MX31_OTG_PM_BIT (1 << 24) 385b591502SStefano Babic 395b591502SStefano Babic #define MX31_H2_SIC_SHIFT 21 405b591502SStefano Babic #define MX31_H2_SIC_MASK (0x3 << MX31_H2_SIC_SHIFT) 415b591502SStefano Babic #define MX31_H2_PM_BIT (1 << 16) 425b591502SStefano Babic #define MX31_H2_DT_BIT (1 << 5) 435b591502SStefano Babic 445b591502SStefano Babic #define MX31_H1_SIC_SHIFT 13 455b591502SStefano Babic #define MX31_H1_SIC_MASK (0x3 << MX31_H1_SIC_SHIFT) 465b591502SStefano Babic #define MX31_H1_PM_BIT (1 << 8) 475b591502SStefano Babic #define MX31_H1_DT_BIT (1 << 4) 485b591502SStefano Babic 4971a5c55bSBenoît Thébaudeau #define MX35_OTG_SIC_SHIFT 29 5071a5c55bSBenoît Thébaudeau #define MX35_OTG_SIC_MASK (0x3 << MX35_OTG_SIC_SHIFT) 5171a5c55bSBenoît Thébaudeau #define MX35_OTG_PM_BIT (1 << 24) 5271a5c55bSBenoît Thébaudeau #define MX35_OTG_PP_BIT (1 << 11) 5371a5c55bSBenoît Thébaudeau #define MX35_OTG_OCPOL_BIT (1 << 3) 5471a5c55bSBenoît Thébaudeau 5571a5c55bSBenoît Thébaudeau #define MX35_H1_SIC_SHIFT 21 5671a5c55bSBenoît Thébaudeau #define MX35_H1_SIC_MASK (0x3 << MX35_H1_SIC_SHIFT) 5771a5c55bSBenoît Thébaudeau #define MX35_H1_PP_BIT (1 << 18) 58ed0a6fcfSBenoît Thébaudeau #define MX35_H1_PM_BIT (1 << 16) 5971a5c55bSBenoît Thébaudeau #define MX35_H1_IPPUE_UP_BIT (1 << 7) 6071a5c55bSBenoît Thébaudeau #define MX35_H1_IPPUE_DOWN_BIT (1 << 6) 6171a5c55bSBenoît Thébaudeau #define MX35_H1_TLL_BIT (1 << 5) 6271a5c55bSBenoît Thébaudeau #define MX35_H1_USBTE_BIT (1 << 4) 6371a5c55bSBenoît Thébaudeau #define MX35_H1_OCPOL_BIT (1 << 2) 6471a5c55bSBenoît Thébaudeau 655b591502SStefano Babic static int mxc_set_usbcontrol(int port, unsigned int flags) 665b591502SStefano Babic { 675b591502SStefano Babic unsigned int v; 68dddb7c9fSMatthias Weisser 69dddb7c9fSMatthias Weisser v = readl(IMX_USB_BASE + USBCTRL_OTGBASE_OFFSET); 709fa3d093SBenoît Thébaudeau #if defined(CONFIG_MX25) 719fa3d093SBenoît Thébaudeau switch (port) { 729fa3d093SBenoît Thébaudeau case 0: /* OTG port */ 739fa3d093SBenoît Thébaudeau v &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PM_BIT | MX25_OTG_PP_BIT | 749fa3d093SBenoît Thébaudeau MX25_OTG_OCPOL_BIT); 759fa3d093SBenoît Thébaudeau v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT; 765b591502SStefano Babic 779fa3d093SBenoît Thébaudeau if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) 789fa3d093SBenoît Thébaudeau v |= MX25_OTG_PM_BIT; 799fa3d093SBenoît Thébaudeau 809fa3d093SBenoît Thébaudeau if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) 819fa3d093SBenoît Thébaudeau v |= MX25_OTG_PP_BIT; 829fa3d093SBenoît Thébaudeau 839fa3d093SBenoît Thébaudeau if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)) 849fa3d093SBenoît Thébaudeau v |= MX25_OTG_OCPOL_BIT; 859fa3d093SBenoît Thébaudeau 869fa3d093SBenoît Thébaudeau break; 879fa3d093SBenoît Thébaudeau case 1: /* H1 port */ 889fa3d093SBenoît Thébaudeau v &= ~(MX25_H1_SIC_MASK | MX25_H1_PM_BIT | MX25_H1_PP_BIT | 899fa3d093SBenoît Thébaudeau MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT | 909fa3d093SBenoît Thébaudeau MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT | 919fa3d093SBenoît Thébaudeau MX25_H1_IPPUE_UP_BIT); 929fa3d093SBenoît Thébaudeau v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT; 939fa3d093SBenoît Thébaudeau 949fa3d093SBenoît Thébaudeau if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) 959fa3d093SBenoît Thébaudeau v |= MX25_H1_PM_BIT; 969fa3d093SBenoît Thébaudeau 979fa3d093SBenoît Thébaudeau if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) 989fa3d093SBenoît Thébaudeau v |= MX25_H1_PP_BIT; 999fa3d093SBenoît Thébaudeau 1009fa3d093SBenoît Thébaudeau if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)) 1019fa3d093SBenoît Thébaudeau v |= MX25_H1_OCPOL_BIT; 1029fa3d093SBenoît Thébaudeau 1039fa3d093SBenoît Thébaudeau if (!(flags & MXC_EHCI_TTL_ENABLED)) 1049fa3d093SBenoît Thébaudeau v |= MX25_H1_TLL_BIT; 1059fa3d093SBenoît Thébaudeau 1069fa3d093SBenoît Thébaudeau if (flags & MXC_EHCI_INTERNAL_PHY) 1079fa3d093SBenoît Thébaudeau v |= MX25_H1_USBTE_BIT; 1089fa3d093SBenoît Thébaudeau 1099fa3d093SBenoît Thébaudeau if (flags & MXC_EHCI_IPPUE_DOWN) 1109fa3d093SBenoît Thébaudeau v |= MX25_H1_IPPUE_DOWN_BIT; 1119fa3d093SBenoît Thébaudeau 1129fa3d093SBenoît Thébaudeau if (flags & MXC_EHCI_IPPUE_UP) 1139fa3d093SBenoît Thébaudeau v |= MX25_H1_IPPUE_UP_BIT; 1149fa3d093SBenoît Thébaudeau 1159fa3d093SBenoît Thébaudeau break; 1169fa3d093SBenoît Thébaudeau default: 1179fa3d093SBenoît Thébaudeau return -EINVAL; 1189fa3d093SBenoît Thébaudeau } 1199fa3d093SBenoît Thébaudeau #elif defined(CONFIG_MX31) 1205b591502SStefano Babic switch (port) { 1215b591502SStefano Babic case 0: /* OTG port */ 1225b591502SStefano Babic v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT); 123164738e9SBenoît Thébaudeau v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_OTG_SIC_SHIFT; 124164738e9SBenoît Thébaudeau 1255b591502SStefano Babic if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) 1265b591502SStefano Babic v |= MX31_OTG_PM_BIT; 1275b591502SStefano Babic 1285b591502SStefano Babic break; 1295b591502SStefano Babic case 1: /* H1 port */ 130164738e9SBenoît Thébaudeau v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT); 131164738e9SBenoît Thébaudeau v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_H1_SIC_SHIFT; 132164738e9SBenoît Thébaudeau 1335b591502SStefano Babic if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) 1345b591502SStefano Babic v |= MX31_H1_PM_BIT; 1355b591502SStefano Babic 1365b591502SStefano Babic if (!(flags & MXC_EHCI_TTL_ENABLED)) 1375b591502SStefano Babic v |= MX31_H1_DT_BIT; 1385b591502SStefano Babic 1395b591502SStefano Babic break; 1405b591502SStefano Babic case 2: /* H2 port */ 141164738e9SBenoît Thébaudeau v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT); 142164738e9SBenoît Thébaudeau v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_H2_SIC_SHIFT; 143164738e9SBenoît Thébaudeau 1445b591502SStefano Babic if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) 1455b591502SStefano Babic v |= MX31_H2_PM_BIT; 1465b591502SStefano Babic 1475b591502SStefano Babic if (!(flags & MXC_EHCI_TTL_ENABLED)) 1485b591502SStefano Babic v |= MX31_H2_DT_BIT; 1495b591502SStefano Babic 1505b591502SStefano Babic break; 1515b591502SStefano Babic default: 1525b591502SStefano Babic return -EINVAL; 1535b591502SStefano Babic } 15471a5c55bSBenoît Thébaudeau #elif defined(CONFIG_MX35) 15571a5c55bSBenoît Thébaudeau switch (port) { 15671a5c55bSBenoît Thébaudeau case 0: /* OTG port */ 15771a5c55bSBenoît Thébaudeau v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT | MX35_OTG_PP_BIT | 15871a5c55bSBenoît Thébaudeau MX35_OTG_OCPOL_BIT); 15971a5c55bSBenoît Thébaudeau v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX35_OTG_SIC_SHIFT; 16071a5c55bSBenoît Thébaudeau 16171a5c55bSBenoît Thébaudeau if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) 16271a5c55bSBenoît Thébaudeau v |= MX35_OTG_PM_BIT; 16371a5c55bSBenoît Thébaudeau 16471a5c55bSBenoît Thébaudeau if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) 16571a5c55bSBenoît Thébaudeau v |= MX35_OTG_PP_BIT; 16671a5c55bSBenoît Thébaudeau 16771a5c55bSBenoît Thébaudeau if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)) 16871a5c55bSBenoît Thébaudeau v |= MX35_OTG_OCPOL_BIT; 16971a5c55bSBenoît Thébaudeau 17071a5c55bSBenoît Thébaudeau break; 17171a5c55bSBenoît Thébaudeau case 1: /* H1 port */ 17271a5c55bSBenoît Thébaudeau v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_PP_BIT | 17371a5c55bSBenoît Thébaudeau MX35_H1_OCPOL_BIT | MX35_H1_TLL_BIT | 17471a5c55bSBenoît Thébaudeau MX35_H1_USBTE_BIT | MX35_H1_IPPUE_DOWN_BIT | 17571a5c55bSBenoît Thébaudeau MX35_H1_IPPUE_UP_BIT); 17671a5c55bSBenoît Thébaudeau v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX35_H1_SIC_SHIFT; 17771a5c55bSBenoît Thébaudeau 17871a5c55bSBenoît Thébaudeau if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) 17971a5c55bSBenoît Thébaudeau v |= MX35_H1_PM_BIT; 18071a5c55bSBenoît Thébaudeau 18171a5c55bSBenoît Thébaudeau if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) 18271a5c55bSBenoît Thébaudeau v |= MX35_H1_PP_BIT; 18371a5c55bSBenoît Thébaudeau 18471a5c55bSBenoît Thébaudeau if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)) 18571a5c55bSBenoît Thébaudeau v |= MX35_H1_OCPOL_BIT; 18671a5c55bSBenoît Thébaudeau 18771a5c55bSBenoît Thébaudeau if (!(flags & MXC_EHCI_TTL_ENABLED)) 18871a5c55bSBenoît Thébaudeau v |= MX35_H1_TLL_BIT; 18971a5c55bSBenoît Thébaudeau 19071a5c55bSBenoît Thébaudeau if (flags & MXC_EHCI_INTERNAL_PHY) 19171a5c55bSBenoît Thébaudeau v |= MX35_H1_USBTE_BIT; 19271a5c55bSBenoît Thébaudeau 19371a5c55bSBenoît Thébaudeau if (flags & MXC_EHCI_IPPUE_DOWN) 19471a5c55bSBenoît Thébaudeau v |= MX35_H1_IPPUE_DOWN_BIT; 19571a5c55bSBenoît Thébaudeau 19671a5c55bSBenoît Thébaudeau if (flags & MXC_EHCI_IPPUE_UP) 19771a5c55bSBenoît Thébaudeau v |= MX35_H1_IPPUE_UP_BIT; 19871a5c55bSBenoît Thébaudeau 19971a5c55bSBenoît Thébaudeau break; 20071a5c55bSBenoît Thébaudeau default: 20171a5c55bSBenoît Thébaudeau return -EINVAL; 20271a5c55bSBenoît Thébaudeau } 203164738e9SBenoît Thébaudeau #else 204164738e9SBenoît Thébaudeau #error MXC EHCI USB driver not supported on this platform 2055b591502SStefano Babic #endif 206dddb7c9fSMatthias Weisser writel(v, IMX_USB_BASE + USBCTRL_OTGBASE_OFFSET); 207164738e9SBenoît Thébaudeau 2085b591502SStefano Babic return 0; 2095b591502SStefano Babic } 2105b591502SStefano Babic 211*127efc4fSTroy Kisky int ehci_hcd_init(int index, enum usb_init_type init, 212*127efc4fSTroy Kisky struct ehci_hccr **hccr, struct ehci_hcor **hcor) 2135b591502SStefano Babic { 2145b591502SStefano Babic struct usb_ehci *ehci; 215dddb7c9fSMatthias Weisser #ifdef CONFIG_MX31 2165b591502SStefano Babic struct clock_control_regs *sc_regs = 2175b591502SStefano Babic (struct clock_control_regs *)CCM_BASE; 2185b591502SStefano Babic 219f55feafdSAnatolij Gustschin __raw_readl(&sc_regs->ccmr); 2205b591502SStefano Babic __raw_writel(__raw_readl(&sc_regs->ccmr) | (1 << 9), &sc_regs->ccmr) ; 221dddb7c9fSMatthias Weisser #endif 2225b591502SStefano Babic 2235b591502SStefano Babic udelay(80); 2245b591502SStefano Babic 225dddb7c9fSMatthias Weisser ehci = (struct usb_ehci *)(IMX_USB_BASE + 22634d33b67SBenoît Thébaudeau IMX_USB_PORT_OFFSET * CONFIG_MXC_USB_PORT); 227676ae068SLucas Stach *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); 228676ae068SLucas Stach *hcor = (struct ehci_hcor *)((uint32_t) *hccr + 229676ae068SLucas Stach HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); 2305b591502SStefano Babic setbits_le32(&ehci->usbmode, CM_HOST); 2315b591502SStefano Babic __raw_writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); 2325b591502SStefano Babic mxc_set_usbcontrol(CONFIG_MXC_USB_PORT, CONFIG_MXC_USB_FLAGS); 23371a5c55bSBenoît Thébaudeau #ifdef CONFIG_MX35 23471a5c55bSBenoît Thébaudeau /* Workaround for ENGcm11601 */ 23571a5c55bSBenoît Thébaudeau __raw_writel(0, &ehci->sbuscfg); 23671a5c55bSBenoît Thébaudeau #endif 2375b591502SStefano Babic 238a2f9bff9SStefano Babic udelay(10000); 239a2f9bff9SStefano Babic 2405b591502SStefano Babic return 0; 2415b591502SStefano Babic } 2425b591502SStefano Babic 2435b591502SStefano Babic /* 2445b591502SStefano Babic * Destroy the appropriate control structures corresponding 2455b591502SStefano Babic * the the EHCI host controller. 2465b591502SStefano Babic */ 247676ae068SLucas Stach int ehci_hcd_stop(int index) 2485b591502SStefano Babic { 2495b591502SStefano Babic return 0; 2505b591502SStefano Babic } 251