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) 409fa3d093SBenoît Thébaudeau #define MX25_H1_PM_BIT (1 << 8) 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 615b591502SStefano Babic static int mxc_set_usbcontrol(int port, unsigned int flags) 625b591502SStefano Babic { 635b591502SStefano Babic unsigned int v; 64dddb7c9fSMatthias Weisser 65dddb7c9fSMatthias Weisser v = readl(IMX_USB_BASE + USBCTRL_OTGBASE_OFFSET); 669fa3d093SBenoît Thébaudeau #if defined(CONFIG_MX25) 679fa3d093SBenoît Thébaudeau switch (port) { 689fa3d093SBenoît Thébaudeau case 0: /* OTG port */ 699fa3d093SBenoît Thébaudeau v &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PM_BIT | MX25_OTG_PP_BIT | 709fa3d093SBenoît Thébaudeau MX25_OTG_OCPOL_BIT); 719fa3d093SBenoît Thébaudeau v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT; 725b591502SStefano Babic 739fa3d093SBenoît Thébaudeau if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) 749fa3d093SBenoît Thébaudeau v |= MX25_OTG_PM_BIT; 759fa3d093SBenoît Thébaudeau 769fa3d093SBenoît Thébaudeau if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) 779fa3d093SBenoît Thébaudeau v |= MX25_OTG_PP_BIT; 789fa3d093SBenoît Thébaudeau 799fa3d093SBenoît Thébaudeau if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)) 809fa3d093SBenoît Thébaudeau v |= MX25_OTG_OCPOL_BIT; 819fa3d093SBenoît Thébaudeau 829fa3d093SBenoît Thébaudeau break; 839fa3d093SBenoît Thébaudeau case 1: /* H1 port */ 849fa3d093SBenoît Thébaudeau v &= ~(MX25_H1_SIC_MASK | MX25_H1_PM_BIT | MX25_H1_PP_BIT | 859fa3d093SBenoît Thébaudeau MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT | 869fa3d093SBenoît Thébaudeau MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT | 879fa3d093SBenoît Thébaudeau MX25_H1_IPPUE_UP_BIT); 889fa3d093SBenoît Thébaudeau v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT; 899fa3d093SBenoît Thébaudeau 909fa3d093SBenoît Thébaudeau if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) 919fa3d093SBenoît Thébaudeau v |= MX25_H1_PM_BIT; 929fa3d093SBenoît Thébaudeau 939fa3d093SBenoît Thébaudeau if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH) 949fa3d093SBenoît Thébaudeau v |= MX25_H1_PP_BIT; 959fa3d093SBenoît Thébaudeau 969fa3d093SBenoît Thébaudeau if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)) 979fa3d093SBenoît Thébaudeau v |= MX25_H1_OCPOL_BIT; 989fa3d093SBenoît Thébaudeau 999fa3d093SBenoît Thébaudeau if (!(flags & MXC_EHCI_TTL_ENABLED)) 1009fa3d093SBenoît Thébaudeau v |= MX25_H1_TLL_BIT; 1019fa3d093SBenoît Thébaudeau 1029fa3d093SBenoît Thébaudeau if (flags & MXC_EHCI_INTERNAL_PHY) 1039fa3d093SBenoît Thébaudeau v |= MX25_H1_USBTE_BIT; 1049fa3d093SBenoît Thébaudeau 1059fa3d093SBenoît Thébaudeau if (flags & MXC_EHCI_IPPUE_DOWN) 1069fa3d093SBenoît Thébaudeau v |= MX25_H1_IPPUE_DOWN_BIT; 1079fa3d093SBenoît Thébaudeau 1089fa3d093SBenoît Thébaudeau if (flags & MXC_EHCI_IPPUE_UP) 1099fa3d093SBenoît Thébaudeau v |= MX25_H1_IPPUE_UP_BIT; 1109fa3d093SBenoît Thébaudeau 1119fa3d093SBenoît Thébaudeau break; 1129fa3d093SBenoît Thébaudeau default: 1139fa3d093SBenoît Thébaudeau return -EINVAL; 1149fa3d093SBenoît Thébaudeau } 1159fa3d093SBenoît Thébaudeau #elif defined(CONFIG_MX31) 1165b591502SStefano Babic switch (port) { 1175b591502SStefano Babic case 0: /* OTG port */ 1185b591502SStefano Babic v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT); 119164738e9SBenoît Thébaudeau v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_OTG_SIC_SHIFT; 120164738e9SBenoît Thébaudeau 1215b591502SStefano Babic if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) 1225b591502SStefano Babic v |= MX31_OTG_PM_BIT; 1235b591502SStefano Babic 1245b591502SStefano Babic break; 1255b591502SStefano Babic case 1: /* H1 port */ 126164738e9SBenoît Thébaudeau v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT); 127164738e9SBenoît Thébaudeau v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_H1_SIC_SHIFT; 128164738e9SBenoît Thébaudeau 1295b591502SStefano Babic if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) 1305b591502SStefano Babic v |= MX31_H1_PM_BIT; 1315b591502SStefano Babic 1325b591502SStefano Babic if (!(flags & MXC_EHCI_TTL_ENABLED)) 1335b591502SStefano Babic v |= MX31_H1_DT_BIT; 1345b591502SStefano Babic 1355b591502SStefano Babic break; 1365b591502SStefano Babic case 2: /* H2 port */ 137164738e9SBenoît Thébaudeau v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT); 138164738e9SBenoît Thébaudeau v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_H2_SIC_SHIFT; 139164738e9SBenoît Thébaudeau 1405b591502SStefano Babic if (!(flags & MXC_EHCI_POWER_PINS_ENABLED)) 1415b591502SStefano Babic v |= MX31_H2_PM_BIT; 1425b591502SStefano Babic 1435b591502SStefano Babic if (!(flags & MXC_EHCI_TTL_ENABLED)) 1445b591502SStefano Babic v |= MX31_H2_DT_BIT; 1455b591502SStefano Babic 1465b591502SStefano Babic break; 1475b591502SStefano Babic default: 1485b591502SStefano Babic return -EINVAL; 1495b591502SStefano Babic } 150164738e9SBenoît Thébaudeau #else 151164738e9SBenoît Thébaudeau #error MXC EHCI USB driver not supported on this platform 1525b591502SStefano Babic #endif 153dddb7c9fSMatthias Weisser writel(v, IMX_USB_BASE + USBCTRL_OTGBASE_OFFSET); 154164738e9SBenoît Thébaudeau 1555b591502SStefano Babic return 0; 1565b591502SStefano Babic } 1575b591502SStefano Babic 158676ae068SLucas Stach int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor) 1595b591502SStefano Babic { 1605b591502SStefano Babic struct usb_ehci *ehci; 161dddb7c9fSMatthias Weisser #ifdef CONFIG_MX31 1625b591502SStefano Babic struct clock_control_regs *sc_regs = 1635b591502SStefano Babic (struct clock_control_regs *)CCM_BASE; 1645b591502SStefano Babic 165f55feafdSAnatolij Gustschin __raw_readl(&sc_regs->ccmr); 1665b591502SStefano Babic __raw_writel(__raw_readl(&sc_regs->ccmr) | (1 << 9), &sc_regs->ccmr) ; 167dddb7c9fSMatthias Weisser #endif 1685b591502SStefano Babic 1695b591502SStefano Babic udelay(80); 1705b591502SStefano Babic 171dddb7c9fSMatthias Weisser ehci = (struct usb_ehci *)(IMX_USB_BASE + 172*34d33b67SBenoît Thébaudeau IMX_USB_PORT_OFFSET * CONFIG_MXC_USB_PORT); 173676ae068SLucas Stach *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); 174676ae068SLucas Stach *hcor = (struct ehci_hcor *)((uint32_t) *hccr + 175676ae068SLucas Stach HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); 1765b591502SStefano Babic setbits_le32(&ehci->usbmode, CM_HOST); 1775b591502SStefano Babic __raw_writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); 1785b591502SStefano Babic mxc_set_usbcontrol(CONFIG_MXC_USB_PORT, CONFIG_MXC_USB_FLAGS); 1795b591502SStefano Babic 180a2f9bff9SStefano Babic udelay(10000); 181a2f9bff9SStefano Babic 1825b591502SStefano Babic return 0; 1835b591502SStefano Babic } 1845b591502SStefano Babic 1855b591502SStefano Babic /* 1865b591502SStefano Babic * Destroy the appropriate control structures corresponding 1875b591502SStefano Babic * the the EHCI host controller. 1885b591502SStefano Babic */ 189676ae068SLucas Stach int ehci_hcd_stop(int index) 1905b591502SStefano Babic { 1915b591502SStefano Babic return 0; 1925b591502SStefano Babic } 193