15b591502SStefano Babic /* 25b591502SStefano Babic * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> 35b591502SStefano Babic * 45b591502SStefano Babic * This program is free software; you can redistribute it and/or modify it 55b591502SStefano Babic * under the terms of the GNU General Public License as published by the 65b591502SStefano Babic * Free Software Foundation; either version 2 of the License, or (at your 75b591502SStefano Babic * option) any later version. 85b591502SStefano Babic * 95b591502SStefano Babic * This program is distributed in the hope that it will be useful, but 105b591502SStefano Babic * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 115b591502SStefano Babic * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 125b591502SStefano Babic * for more details. 135b591502SStefano Babic * 145b591502SStefano Babic * You should have received a copy of the GNU General Public License 155b591502SStefano Babic * along with this program; if not, write to the Free Software Foundation, 165b591502SStefano Babic * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 175b591502SStefano Babic */ 185b591502SStefano Babic 195b591502SStefano Babic 205b591502SStefano Babic #include <common.h> 215b591502SStefano Babic #include <usb.h> 225b591502SStefano Babic #include <asm/io.h> 2386271115SStefano Babic #include <asm/arch/imx-regs.h> 245b591502SStefano Babic #include <usb/ehci-fsl.h> 255b591502SStefano Babic #include <errno.h> 265b591502SStefano Babic 275b591502SStefano Babic #include "ehci.h" 285b591502SStefano Babic 295b591502SStefano Babic #define USBCTRL_OTGBASE_OFFSET 0x600 305b591502SStefano Babic 319fa3d093SBenoît Thébaudeau #define MX25_OTG_SIC_SHIFT 29 329fa3d093SBenoît Thébaudeau #define MX25_OTG_SIC_MASK (0x3 << MX25_OTG_SIC_SHIFT) 339fa3d093SBenoît Thébaudeau #define MX25_OTG_PM_BIT (1 << 24) 349fa3d093SBenoît Thébaudeau #define MX25_OTG_PP_BIT (1 << 11) 359fa3d093SBenoît Thébaudeau #define MX25_OTG_OCPOL_BIT (1 << 3) 369fa3d093SBenoît Thébaudeau 379fa3d093SBenoît Thébaudeau #define MX25_H1_SIC_SHIFT 21 389fa3d093SBenoît Thébaudeau #define MX25_H1_SIC_MASK (0x3 << MX25_H1_SIC_SHIFT) 399fa3d093SBenoît Thébaudeau #define MX25_H1_PP_BIT (1 << 18) 40*fa88ddb7SBenoît Thébaudeau #define MX25_H1_PM_BIT (1 << 16) 419fa3d093SBenoît Thébaudeau #define MX25_H1_IPPUE_UP_BIT (1 << 7) 429fa3d093SBenoît Thébaudeau #define MX25_H1_IPPUE_DOWN_BIT (1 << 6) 439fa3d093SBenoît Thébaudeau #define MX25_H1_TLL_BIT (1 << 5) 449fa3d093SBenoît Thébaudeau #define MX25_H1_USBTE_BIT (1 << 4) 459fa3d093SBenoît Thébaudeau #define MX25_H1_OCPOL_BIT (1 << 2) 46dddb7c9fSMatthias Weisser 475b591502SStefano Babic #define MX31_OTG_SIC_SHIFT 29 485b591502SStefano Babic #define MX31_OTG_SIC_MASK (0x3 << MX31_OTG_SIC_SHIFT) 495b591502SStefano Babic #define MX31_OTG_PM_BIT (1 << 24) 505b591502SStefano Babic 515b591502SStefano Babic #define MX31_H2_SIC_SHIFT 21 525b591502SStefano Babic #define MX31_H2_SIC_MASK (0x3 << MX31_H2_SIC_SHIFT) 535b591502SStefano Babic #define MX31_H2_PM_BIT (1 << 16) 545b591502SStefano Babic #define MX31_H2_DT_BIT (1 << 5) 555b591502SStefano Babic 565b591502SStefano Babic #define MX31_H1_SIC_SHIFT 13 575b591502SStefano Babic #define MX31_H1_SIC_MASK (0x3 << MX31_H1_SIC_SHIFT) 585b591502SStefano Babic #define MX31_H1_PM_BIT (1 << 8) 595b591502SStefano Babic #define MX31_H1_DT_BIT (1 << 4) 605b591502SStefano Babic 6171a5c55bSBenoît Thébaudeau #define MX35_OTG_SIC_SHIFT 29 6271a5c55bSBenoît Thébaudeau #define MX35_OTG_SIC_MASK (0x3 << MX35_OTG_SIC_SHIFT) 6371a5c55bSBenoît Thébaudeau #define MX35_OTG_PM_BIT (1 << 24) 6471a5c55bSBenoît Thébaudeau #define MX35_OTG_PP_BIT (1 << 11) 6571a5c55bSBenoît Thébaudeau #define MX35_OTG_OCPOL_BIT (1 << 3) 6671a5c55bSBenoît Thébaudeau 6771a5c55bSBenoît Thébaudeau #define MX35_H1_SIC_SHIFT 21 6871a5c55bSBenoît Thébaudeau #define MX35_H1_SIC_MASK (0x3 << MX35_H1_SIC_SHIFT) 6971a5c55bSBenoît Thébaudeau #define MX35_H1_PP_BIT (1 << 18) 70ed0a6fcfSBenoît Thébaudeau #define MX35_H1_PM_BIT (1 << 16) 7171a5c55bSBenoît Thébaudeau #define MX35_H1_IPPUE_UP_BIT (1 << 7) 7271a5c55bSBenoît Thébaudeau #define MX35_H1_IPPUE_DOWN_BIT (1 << 6) 7371a5c55bSBenoît Thébaudeau #define MX35_H1_TLL_BIT (1 << 5) 7471a5c55bSBenoît Thébaudeau #define MX35_H1_USBTE_BIT (1 << 4) 7571a5c55bSBenoît Thébaudeau #define MX35_H1_OCPOL_BIT (1 << 2) 7671a5c55bSBenoît Thébaudeau 775b591502SStefano Babic static int mxc_set_usbcontrol(int port, unsigned int flags) 785b591502SStefano Babic { 795b591502SStefano Babic unsigned int v; 80dddb7c9fSMatthias Weisser 81dddb7c9fSMatthias Weisser v = readl(IMX_USB_BASE + USBCTRL_OTGBASE_OFFSET); 829fa3d093SBenoît Thébaudeau #if defined(CONFIG_MX25) 839fa3d093SBenoît Thébaudeau switch (port) { 849fa3d093SBenoît Thébaudeau case 0: /* OTG port */ 859fa3d093SBenoît Thébaudeau v &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PM_BIT | MX25_OTG_PP_BIT | 869fa3d093SBenoît Thébaudeau MX25_OTG_OCPOL_BIT); 879fa3d093SBenoît Thébaudeau v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT; 885b591502SStefano Babic 899fa3d093SBenoît Thébaudeau if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) 909fa3d093SBenoît Thébaudeau v |= MX25_OTG_PM_BIT; 919fa3d093SBenoît Thébaudeau 929fa3d093SBenoît Thébaudeau if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) 939fa3d093SBenoît Thébaudeau v |= MX25_OTG_PP_BIT; 949fa3d093SBenoît Thébaudeau 959fa3d093SBenoît Thébaudeau if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)) 969fa3d093SBenoît Thébaudeau v |= MX25_OTG_OCPOL_BIT; 979fa3d093SBenoît Thébaudeau 989fa3d093SBenoît Thébaudeau break; 999fa3d093SBenoît Thébaudeau case 1: /* H1 port */ 1009fa3d093SBenoît Thébaudeau v &= ~(MX25_H1_SIC_MASK | MX25_H1_PM_BIT | MX25_H1_PP_BIT | 1019fa3d093SBenoît Thébaudeau MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT | 1029fa3d093SBenoît Thébaudeau MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT | 1039fa3d093SBenoît Thébaudeau MX25_H1_IPPUE_UP_BIT); 1049fa3d093SBenoît Thébaudeau v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT; 1059fa3d093SBenoît Thébaudeau 1069fa3d093SBenoît Thébaudeau if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) 1079fa3d093SBenoît Thébaudeau v |= MX25_H1_PM_BIT; 1089fa3d093SBenoît Thébaudeau 1099fa3d093SBenoît Thébaudeau if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) 1109fa3d093SBenoît Thébaudeau v |= MX25_H1_PP_BIT; 1119fa3d093SBenoît Thébaudeau 1129fa3d093SBenoît Thébaudeau if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)) 1139fa3d093SBenoît Thébaudeau v |= MX25_H1_OCPOL_BIT; 1149fa3d093SBenoît Thébaudeau 1159fa3d093SBenoît Thébaudeau if (!(flags & MXC_EHCI_TTL_ENABLED)) 1169fa3d093SBenoît Thébaudeau v |= MX25_H1_TLL_BIT; 1179fa3d093SBenoît Thébaudeau 1189fa3d093SBenoît Thébaudeau if (flags & MXC_EHCI_INTERNAL_PHY) 1199fa3d093SBenoît Thébaudeau v |= MX25_H1_USBTE_BIT; 1209fa3d093SBenoît Thébaudeau 1219fa3d093SBenoît Thébaudeau if (flags & MXC_EHCI_IPPUE_DOWN) 1229fa3d093SBenoît Thébaudeau v |= MX25_H1_IPPUE_DOWN_BIT; 1239fa3d093SBenoît Thébaudeau 1249fa3d093SBenoît Thébaudeau if (flags & MXC_EHCI_IPPUE_UP) 1259fa3d093SBenoît Thébaudeau v |= MX25_H1_IPPUE_UP_BIT; 1269fa3d093SBenoît Thébaudeau 1279fa3d093SBenoît Thébaudeau break; 1289fa3d093SBenoît Thébaudeau default: 1299fa3d093SBenoît Thébaudeau return -EINVAL; 1309fa3d093SBenoît Thébaudeau } 1319fa3d093SBenoît Thébaudeau #elif defined(CONFIG_MX31) 1325b591502SStefano Babic switch (port) { 1335b591502SStefano Babic case 0: /* OTG port */ 1345b591502SStefano Babic v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT); 135164738e9SBenoît Thébaudeau v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_OTG_SIC_SHIFT; 136164738e9SBenoît Thébaudeau 1375b591502SStefano Babic if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) 1385b591502SStefano Babic v |= MX31_OTG_PM_BIT; 1395b591502SStefano Babic 1405b591502SStefano Babic break; 1415b591502SStefano Babic case 1: /* H1 port */ 142164738e9SBenoît Thébaudeau v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT); 143164738e9SBenoît Thébaudeau v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_H1_SIC_SHIFT; 144164738e9SBenoît Thébaudeau 1455b591502SStefano Babic if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) 1465b591502SStefano Babic v |= MX31_H1_PM_BIT; 1475b591502SStefano Babic 1485b591502SStefano Babic if (!(flags & MXC_EHCI_TTL_ENABLED)) 1495b591502SStefano Babic v |= MX31_H1_DT_BIT; 1505b591502SStefano Babic 1515b591502SStefano Babic break; 1525b591502SStefano Babic case 2: /* H2 port */ 153164738e9SBenoît Thébaudeau v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT); 154164738e9SBenoît Thébaudeau v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_H2_SIC_SHIFT; 155164738e9SBenoît Thébaudeau 1565b591502SStefano Babic if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) 1575b591502SStefano Babic v |= MX31_H2_PM_BIT; 1585b591502SStefano Babic 1595b591502SStefano Babic if (!(flags & MXC_EHCI_TTL_ENABLED)) 1605b591502SStefano Babic v |= MX31_H2_DT_BIT; 1615b591502SStefano Babic 1625b591502SStefano Babic break; 1635b591502SStefano Babic default: 1645b591502SStefano Babic return -EINVAL; 1655b591502SStefano Babic } 16671a5c55bSBenoît Thébaudeau #elif defined(CONFIG_MX35) 16771a5c55bSBenoît Thébaudeau switch (port) { 16871a5c55bSBenoît Thébaudeau case 0: /* OTG port */ 16971a5c55bSBenoît Thébaudeau v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT | MX35_OTG_PP_BIT | 17071a5c55bSBenoît Thébaudeau MX35_OTG_OCPOL_BIT); 17171a5c55bSBenoît Thébaudeau v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX35_OTG_SIC_SHIFT; 17271a5c55bSBenoît Thébaudeau 17371a5c55bSBenoît Thébaudeau if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) 17471a5c55bSBenoît Thébaudeau v |= MX35_OTG_PM_BIT; 17571a5c55bSBenoît Thébaudeau 17671a5c55bSBenoît Thébaudeau if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) 17771a5c55bSBenoît Thébaudeau v |= MX35_OTG_PP_BIT; 17871a5c55bSBenoît Thébaudeau 17971a5c55bSBenoît Thébaudeau if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)) 18071a5c55bSBenoît Thébaudeau v |= MX35_OTG_OCPOL_BIT; 18171a5c55bSBenoît Thébaudeau 18271a5c55bSBenoît Thébaudeau break; 18371a5c55bSBenoît Thébaudeau case 1: /* H1 port */ 18471a5c55bSBenoît Thébaudeau v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_PP_BIT | 18571a5c55bSBenoît Thébaudeau MX35_H1_OCPOL_BIT | MX35_H1_TLL_BIT | 18671a5c55bSBenoît Thébaudeau MX35_H1_USBTE_BIT | MX35_H1_IPPUE_DOWN_BIT | 18771a5c55bSBenoît Thébaudeau MX35_H1_IPPUE_UP_BIT); 18871a5c55bSBenoît Thébaudeau v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX35_H1_SIC_SHIFT; 18971a5c55bSBenoît Thébaudeau 19071a5c55bSBenoît Thébaudeau if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) 19171a5c55bSBenoît Thébaudeau v |= MX35_H1_PM_BIT; 19271a5c55bSBenoît Thébaudeau 19371a5c55bSBenoît Thébaudeau if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) 19471a5c55bSBenoît Thébaudeau v |= MX35_H1_PP_BIT; 19571a5c55bSBenoît Thébaudeau 19671a5c55bSBenoît Thébaudeau if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)) 19771a5c55bSBenoît Thébaudeau v |= MX35_H1_OCPOL_BIT; 19871a5c55bSBenoît Thébaudeau 19971a5c55bSBenoît Thébaudeau if (!(flags & MXC_EHCI_TTL_ENABLED)) 20071a5c55bSBenoît Thébaudeau v |= MX35_H1_TLL_BIT; 20171a5c55bSBenoît Thébaudeau 20271a5c55bSBenoît Thébaudeau if (flags & MXC_EHCI_INTERNAL_PHY) 20371a5c55bSBenoît Thébaudeau v |= MX35_H1_USBTE_BIT; 20471a5c55bSBenoît Thébaudeau 20571a5c55bSBenoît Thébaudeau if (flags & MXC_EHCI_IPPUE_DOWN) 20671a5c55bSBenoît Thébaudeau v |= MX35_H1_IPPUE_DOWN_BIT; 20771a5c55bSBenoît Thébaudeau 20871a5c55bSBenoît Thébaudeau if (flags & MXC_EHCI_IPPUE_UP) 20971a5c55bSBenoît Thébaudeau v |= MX35_H1_IPPUE_UP_BIT; 21071a5c55bSBenoît Thébaudeau 21171a5c55bSBenoît Thébaudeau break; 21271a5c55bSBenoît Thébaudeau default: 21371a5c55bSBenoît Thébaudeau return -EINVAL; 21471a5c55bSBenoît Thébaudeau } 215164738e9SBenoît Thébaudeau #else 216164738e9SBenoît Thébaudeau #error MXC EHCI USB driver not supported on this platform 2175b591502SStefano Babic #endif 218dddb7c9fSMatthias Weisser writel(v, IMX_USB_BASE + USBCTRL_OTGBASE_OFFSET); 219164738e9SBenoît Thébaudeau 2205b591502SStefano Babic return 0; 2215b591502SStefano Babic } 2225b591502SStefano Babic 223676ae068SLucas Stach int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor) 2245b591502SStefano Babic { 2255b591502SStefano Babic struct usb_ehci *ehci; 226dddb7c9fSMatthias Weisser #ifdef CONFIG_MX31 2275b591502SStefano Babic struct clock_control_regs *sc_regs = 2285b591502SStefano Babic (struct clock_control_regs *)CCM_BASE; 2295b591502SStefano Babic 230f55feafdSAnatolij Gustschin __raw_readl(&sc_regs->ccmr); 2315b591502SStefano Babic __raw_writel(__raw_readl(&sc_regs->ccmr) | (1 << 9), &sc_regs->ccmr) ; 232dddb7c9fSMatthias Weisser #endif 2335b591502SStefano Babic 2345b591502SStefano Babic udelay(80); 2355b591502SStefano Babic 236dddb7c9fSMatthias Weisser ehci = (struct usb_ehci *)(IMX_USB_BASE + 23734d33b67SBenoît Thébaudeau IMX_USB_PORT_OFFSET * CONFIG_MXC_USB_PORT); 238676ae068SLucas Stach *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); 239676ae068SLucas Stach *hcor = (struct ehci_hcor *)((uint32_t) *hccr + 240676ae068SLucas Stach HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); 2415b591502SStefano Babic setbits_le32(&ehci->usbmode, CM_HOST); 2425b591502SStefano Babic __raw_writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); 2435b591502SStefano Babic mxc_set_usbcontrol(CONFIG_MXC_USB_PORT, CONFIG_MXC_USB_FLAGS); 24471a5c55bSBenoît Thébaudeau #ifdef CONFIG_MX35 24571a5c55bSBenoît Thébaudeau /* Workaround for ENGcm11601 */ 24671a5c55bSBenoît Thébaudeau __raw_writel(0, &ehci->sbuscfg); 24771a5c55bSBenoît Thébaudeau #endif 2485b591502SStefano Babic 249a2f9bff9SStefano Babic udelay(10000); 250a2f9bff9SStefano Babic 2515b591502SStefano Babic return 0; 2525b591502SStefano Babic } 2535b591502SStefano Babic 2545b591502SStefano Babic /* 2555b591502SStefano Babic * Destroy the appropriate control structures corresponding 2565b591502SStefano Babic * the the EHCI host controller. 2575b591502SStefano Babic */ 258676ae068SLucas Stach int ehci_hcd_stop(int index) 2595b591502SStefano Babic { 2605b591502SStefano Babic return 0; 2615b591502SStefano Babic } 262