11ca56202SWolfgang Grandegger /* 21ca56202SWolfgang Grandegger * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> 31ca56202SWolfgang Grandegger * Copyright (C) 2010 Freescale Semiconductor, Inc. 41ca56202SWolfgang Grandegger * 51ca56202SWolfgang Grandegger * This program is free software; you can redistribute it and/or modify it 61ca56202SWolfgang Grandegger * under the terms of the GNU General Public License as published by the 71ca56202SWolfgang Grandegger * Free Software Foundation; either version 2 of the License, or (at your 81ca56202SWolfgang Grandegger * option) any later version. 91ca56202SWolfgang Grandegger * 101ca56202SWolfgang Grandegger * This program is distributed in the hope that it will be useful, but 111ca56202SWolfgang Grandegger * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 121ca56202SWolfgang Grandegger * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 131ca56202SWolfgang Grandegger * for more details. 141ca56202SWolfgang Grandegger */ 151ca56202SWolfgang Grandegger 161ca56202SWolfgang Grandegger #include <common.h> 171ca56202SWolfgang Grandegger #include <usb.h> 181ca56202SWolfgang Grandegger #include <errno.h> 191ca56202SWolfgang Grandegger #include <linux/compiler.h> 201ca56202SWolfgang Grandegger #include <usb/ehci-fsl.h> 211ca56202SWolfgang Grandegger #include <asm/io.h> 221ca56202SWolfgang Grandegger #include <asm/arch/imx-regs.h> 231ca56202SWolfgang Grandegger #include <asm/arch/clock.h> 241ca56202SWolfgang Grandegger #include <asm/arch/mx5x_pins.h> 251b80f270SMarek Vasut #include <asm/arch/iomux.h> 261ca56202SWolfgang Grandegger 271ca56202SWolfgang Grandegger #include "ehci.h" 281ca56202SWolfgang Grandegger 291ca56202SWolfgang Grandegger #define MX5_USBOTHER_REGS_OFFSET 0x800 301ca56202SWolfgang Grandegger 311ca56202SWolfgang Grandegger 321ca56202SWolfgang Grandegger #define MXC_OTG_OFFSET 0 331ca56202SWolfgang Grandegger #define MXC_H1_OFFSET 0x200 341ca56202SWolfgang Grandegger #define MXC_H2_OFFSET 0x400 351ca56202SWolfgang Grandegger 361ca56202SWolfgang Grandegger #define MXC_USBCTRL_OFFSET 0 371ca56202SWolfgang Grandegger #define MXC_USB_PHY_CTR_FUNC_OFFSET 0x8 381ca56202SWolfgang Grandegger #define MXC_USB_PHY_CTR_FUNC2_OFFSET 0xc 391ca56202SWolfgang Grandegger #define MXC_USB_CTRL_1_OFFSET 0x10 401ca56202SWolfgang Grandegger #define MXC_USBH2CTRL_OFFSET 0x14 411ca56202SWolfgang Grandegger 421ca56202SWolfgang Grandegger /* USB_CTRL */ 431ca56202SWolfgang Grandegger #define MXC_OTG_UCTRL_OWIE_BIT (1 << 27) /* OTG wakeup intr enable */ 441ca56202SWolfgang Grandegger #define MXC_OTG_UCTRL_OPM_BIT (1 << 24) /* OTG power mask */ 451ca56202SWolfgang Grandegger #define MXC_H1_UCTRL_H1UIE_BIT (1 << 12) /* Host1 ULPI interrupt enable */ 461ca56202SWolfgang Grandegger #define MXC_H1_UCTRL_H1WIE_BIT (1 << 11) /* HOST1 wakeup intr enable */ 471ca56202SWolfgang Grandegger #define MXC_H1_UCTRL_H1PM_BIT (1 << 8) /* HOST1 power mask */ 481ca56202SWolfgang Grandegger 491ca56202SWolfgang Grandegger /* USB_PHY_CTRL_FUNC */ 501ca56202SWolfgang Grandegger #define MXC_OTG_PHYCTRL_OC_DIS_BIT (1 << 8) /* OTG Disable Overcurrent Event */ 511ca56202SWolfgang Grandegger #define MXC_H1_OC_DIS_BIT (1 << 5) /* UH1 Disable Overcurrent Event */ 521ca56202SWolfgang Grandegger 531ca56202SWolfgang Grandegger /* USBH2CTRL */ 541ca56202SWolfgang Grandegger #define MXC_H2_UCTRL_H2UIE_BIT (1 << 8) 551ca56202SWolfgang Grandegger #define MXC_H2_UCTRL_H2WIE_BIT (1 << 7) 561ca56202SWolfgang Grandegger #define MXC_H2_UCTRL_H2PM_BIT (1 << 4) 571ca56202SWolfgang Grandegger 581ca56202SWolfgang Grandegger /* USB_CTRL_1 */ 591ca56202SWolfgang Grandegger #define MXC_USB_CTRL_UH1_EXT_CLK_EN (1 << 25) 601ca56202SWolfgang Grandegger 610f8c86b5SMarek Vasut /* USB pin configuration */ 620f8c86b5SMarek Vasut #define USB_PAD_CONFIG (PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST | \ 630f8c86b5SMarek Vasut PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | \ 640f8c86b5SMarek Vasut PAD_CTL_HYS_ENABLE | PAD_CTL_PUE_PULL) 650f8c86b5SMarek Vasut 660f8c86b5SMarek Vasut #ifdef CONFIG_MX51 670f8c86b5SMarek Vasut /* 680f8c86b5SMarek Vasut * Configure the MX51 USB H1 IOMUX 690f8c86b5SMarek Vasut */ 700f8c86b5SMarek Vasut void setup_iomux_usb_h1(void) 710f8c86b5SMarek Vasut { 720f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_USBH1_STP, IOMUX_CONFIG_ALT0); 730f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_USBH1_STP, USB_PAD_CONFIG); 740f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_USBH1_CLK, IOMUX_CONFIG_ALT0); 750f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_USBH1_CLK, USB_PAD_CONFIG); 760f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_USBH1_DIR, IOMUX_CONFIG_ALT0); 770f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_USBH1_DIR, USB_PAD_CONFIG); 780f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_USBH1_NXT, IOMUX_CONFIG_ALT0); 790f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_USBH1_NXT, USB_PAD_CONFIG); 800f8c86b5SMarek Vasut 810f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_USBH1_DATA0, IOMUX_CONFIG_ALT0); 820f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_USBH1_DATA0, USB_PAD_CONFIG); 830f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_USBH1_DATA1, IOMUX_CONFIG_ALT0); 840f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_USBH1_DATA1, USB_PAD_CONFIG); 850f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_USBH1_DATA2, IOMUX_CONFIG_ALT0); 860f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_USBH1_DATA2, USB_PAD_CONFIG); 870f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_USBH1_DATA3, IOMUX_CONFIG_ALT0); 880f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_USBH1_DATA3, USB_PAD_CONFIG); 890f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_USBH1_DATA4, IOMUX_CONFIG_ALT0); 900f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_USBH1_DATA4, USB_PAD_CONFIG); 910f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_USBH1_DATA5, IOMUX_CONFIG_ALT0); 920f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_USBH1_DATA5, USB_PAD_CONFIG); 930f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_USBH1_DATA6, IOMUX_CONFIG_ALT0); 940f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_USBH1_DATA6, USB_PAD_CONFIG); 950f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_USBH1_DATA7, IOMUX_CONFIG_ALT0); 960f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_USBH1_DATA7, USB_PAD_CONFIG); 970f8c86b5SMarek Vasut } 980f8c86b5SMarek Vasut 990f8c86b5SMarek Vasut /* 1000f8c86b5SMarek Vasut * Configure the MX51 USB H2 IOMUX 1010f8c86b5SMarek Vasut */ 1020f8c86b5SMarek Vasut void setup_iomux_usb_h2(void) 1030f8c86b5SMarek Vasut { 1040f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_EIM_A24, IOMUX_CONFIG_ALT2); 1050f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_EIM_A24, USB_PAD_CONFIG); 1060f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_EIM_A25, IOMUX_CONFIG_ALT2); 1070f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_EIM_A25, USB_PAD_CONFIG); 1080f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_EIM_A26, IOMUX_CONFIG_ALT2); 1090f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_EIM_A26, USB_PAD_CONFIG); 1100f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_EIM_A27, IOMUX_CONFIG_ALT2); 1110f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_EIM_A27, USB_PAD_CONFIG); 1120f8c86b5SMarek Vasut 1130f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_EIM_D16, IOMUX_CONFIG_ALT2); 1140f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_EIM_D16, USB_PAD_CONFIG); 1150f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_EIM_D17, IOMUX_CONFIG_ALT2); 1160f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_EIM_D17, USB_PAD_CONFIG); 1170f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_EIM_D18, IOMUX_CONFIG_ALT2); 1180f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_EIM_D18, USB_PAD_CONFIG); 1190f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_EIM_D19, IOMUX_CONFIG_ALT2); 1200f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_EIM_D19, USB_PAD_CONFIG); 1210f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_EIM_D20, IOMUX_CONFIG_ALT2); 1220f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_EIM_D20, USB_PAD_CONFIG); 1230f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_EIM_D21, IOMUX_CONFIG_ALT2); 1240f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_EIM_D21, USB_PAD_CONFIG); 1250f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_EIM_D22, IOMUX_CONFIG_ALT2); 1260f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_EIM_D22, USB_PAD_CONFIG); 1270f8c86b5SMarek Vasut mxc_request_iomux(MX51_PIN_EIM_D23, IOMUX_CONFIG_ALT2); 1280f8c86b5SMarek Vasut mxc_iomux_set_pad(MX51_PIN_EIM_D23, USB_PAD_CONFIG); 1290f8c86b5SMarek Vasut } 1300f8c86b5SMarek Vasut #endif 1310f8c86b5SMarek Vasut 1321ca56202SWolfgang Grandegger int mxc_set_usbcontrol(int port, unsigned int flags) 1331ca56202SWolfgang Grandegger { 1341ca56202SWolfgang Grandegger unsigned int v; 1351ca56202SWolfgang Grandegger void __iomem *usb_base = (void __iomem *)OTG_BASE_ADDR; 1361ca56202SWolfgang Grandegger void __iomem *usbother_base; 1371ca56202SWolfgang Grandegger int ret = 0; 1381ca56202SWolfgang Grandegger 1391ca56202SWolfgang Grandegger usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; 1401ca56202SWolfgang Grandegger 1411ca56202SWolfgang Grandegger switch (port) { 1421ca56202SWolfgang Grandegger case 0: /* OTG port */ 1431ca56202SWolfgang Grandegger if (flags & MXC_EHCI_INTERNAL_PHY) { 1441ca56202SWolfgang Grandegger v = __raw_readl(usbother_base + 1451ca56202SWolfgang Grandegger MXC_USB_PHY_CTR_FUNC_OFFSET); 1461ca56202SWolfgang Grandegger if (flags & MXC_EHCI_POWER_PINS_ENABLED) 1471ca56202SWolfgang Grandegger /* OC/USBPWR is not used */ 1481ca56202SWolfgang Grandegger v |= MXC_OTG_PHYCTRL_OC_DIS_BIT; 1491ca56202SWolfgang Grandegger else 1501ca56202SWolfgang Grandegger /* OC/USBPWR is used */ 1511ca56202SWolfgang Grandegger v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT; 1521ca56202SWolfgang Grandegger __raw_writel(v, usbother_base + 1531ca56202SWolfgang Grandegger MXC_USB_PHY_CTR_FUNC_OFFSET); 1541ca56202SWolfgang Grandegger 1551ca56202SWolfgang Grandegger v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET); 1561ca56202SWolfgang Grandegger if (flags & MXC_EHCI_POWER_PINS_ENABLED) 1571ca56202SWolfgang Grandegger v |= MXC_OTG_UCTRL_OPM_BIT; 1581ca56202SWolfgang Grandegger else 1591ca56202SWolfgang Grandegger v &= ~MXC_OTG_UCTRL_OPM_BIT; 1601ca56202SWolfgang Grandegger __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET); 1611ca56202SWolfgang Grandegger } 1621ca56202SWolfgang Grandegger break; 1631ca56202SWolfgang Grandegger case 1: /* Host 1 Host ULPI */ 1641ca56202SWolfgang Grandegger #ifdef CONFIG_MX51 1651ca56202SWolfgang Grandegger /* The clock for the USBH1 ULPI port will come externally 1661ca56202SWolfgang Grandegger from the PHY. */ 1671ca56202SWolfgang Grandegger v = __raw_readl(usbother_base + MXC_USB_CTRL_1_OFFSET); 1681ca56202SWolfgang Grandegger __raw_writel(v | MXC_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + 1691ca56202SWolfgang Grandegger MXC_USB_CTRL_1_OFFSET); 1701ca56202SWolfgang Grandegger #endif 1711ca56202SWolfgang Grandegger 1721ca56202SWolfgang Grandegger v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET); 1731ca56202SWolfgang Grandegger if (flags & MXC_EHCI_POWER_PINS_ENABLED) 1741ca56202SWolfgang Grandegger v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used */ 1751ca56202SWolfgang Grandegger else 1761ca56202SWolfgang Grandegger v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used */ 1771ca56202SWolfgang Grandegger __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET); 1781ca56202SWolfgang Grandegger 1791ca56202SWolfgang Grandegger v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); 1801ca56202SWolfgang Grandegger if (flags & MXC_EHCI_POWER_PINS_ENABLED) 1811ca56202SWolfgang Grandegger v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */ 1821ca56202SWolfgang Grandegger else 1831ca56202SWolfgang Grandegger v |= MXC_H1_OC_DIS_BIT; /* OC is not used */ 1841ca56202SWolfgang Grandegger __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); 1851ca56202SWolfgang Grandegger 1861ca56202SWolfgang Grandegger break; 1871ca56202SWolfgang Grandegger case 2: /* Host 2 ULPI */ 1881ca56202SWolfgang Grandegger v = __raw_readl(usbother_base + MXC_USBH2CTRL_OFFSET); 1891ca56202SWolfgang Grandegger if (flags & MXC_EHCI_POWER_PINS_ENABLED) 1901ca56202SWolfgang Grandegger v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used */ 1911ca56202SWolfgang Grandegger else 1921ca56202SWolfgang Grandegger v |= MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used */ 1931ca56202SWolfgang Grandegger 1941ca56202SWolfgang Grandegger __raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET); 1951ca56202SWolfgang Grandegger break; 1961ca56202SWolfgang Grandegger } 1971ca56202SWolfgang Grandegger 1981ca56202SWolfgang Grandegger return ret; 1991ca56202SWolfgang Grandegger } 2001ca56202SWolfgang Grandegger 2011b80f270SMarek Vasut void __board_ehci_hcd_postinit(struct usb_ehci *ehci, int port) 2021b80f270SMarek Vasut { 2031b80f270SMarek Vasut } 2041b80f270SMarek Vasut 2051b80f270SMarek Vasut void board_ehci_hcd_postinit(struct usb_ehci *ehci, int port) 2061b80f270SMarek Vasut __attribute((weak, alias("__board_ehci_hcd_postinit"))); 2071b80f270SMarek Vasut 208676ae068SLucas Stach int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor) 2091ca56202SWolfgang Grandegger { 2101ca56202SWolfgang Grandegger struct usb_ehci *ehci; 2111ca56202SWolfgang Grandegger #ifdef CONFIG_MX53 2121ca56202SWolfgang Grandegger struct clkctl *sc_regs = (struct clkctl *)CCM_BASE_ADDR; 2131ca56202SWolfgang Grandegger u32 reg; 2141ca56202SWolfgang Grandegger 2151ca56202SWolfgang Grandegger reg = __raw_readl(&sc_regs->cscmr1) & ~(1 << 26); 2161ca56202SWolfgang Grandegger /* derive USB PHY clock multiplexer from PLL3 */ 2171ca56202SWolfgang Grandegger reg |= 1 << 26; 2181ca56202SWolfgang Grandegger __raw_writel(reg, &sc_regs->cscmr1); 2191ca56202SWolfgang Grandegger #endif 2201ca56202SWolfgang Grandegger 2211ca56202SWolfgang Grandegger set_usboh3_clk(); 2221ca56202SWolfgang Grandegger enable_usboh3_clk(1); 223*414e1660SBenoît Thébaudeau set_usb_phy_clk(); 224*414e1660SBenoît Thébaudeau enable_usb_phy1_clk(1); 2251ca56202SWolfgang Grandegger enable_usb_phy2_clk(1); 2261ca56202SWolfgang Grandegger mdelay(1); 2271ca56202SWolfgang Grandegger 2281b80f270SMarek Vasut /* Do board specific initialization */ 2291ca56202SWolfgang Grandegger board_ehci_hcd_init(CONFIG_MXC_USB_PORT); 2301ca56202SWolfgang Grandegger 2311ca56202SWolfgang Grandegger ehci = (struct usb_ehci *)(OTG_BASE_ADDR + 2321ca56202SWolfgang Grandegger (0x200 * CONFIG_MXC_USB_PORT)); 233676ae068SLucas Stach *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); 234676ae068SLucas Stach *hcor = (struct ehci_hcor *)((uint32_t)*hccr + 235676ae068SLucas Stach HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); 2361ca56202SWolfgang Grandegger setbits_le32(&ehci->usbmode, CM_HOST); 2371ca56202SWolfgang Grandegger 2381ca56202SWolfgang Grandegger __raw_writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); 2391ca56202SWolfgang Grandegger setbits_le32(&ehci->portsc, USB_EN); 2401ca56202SWolfgang Grandegger 2411ca56202SWolfgang Grandegger mxc_set_usbcontrol(CONFIG_MXC_USB_PORT, CONFIG_MXC_USB_FLAGS); 2421ca56202SWolfgang Grandegger mdelay(10); 2431ca56202SWolfgang Grandegger 2441b80f270SMarek Vasut /* Do board specific post-initialization */ 2451b80f270SMarek Vasut board_ehci_hcd_postinit(ehci, CONFIG_MXC_USB_PORT); 2461b80f270SMarek Vasut 2471ca56202SWolfgang Grandegger return 0; 2481ca56202SWolfgang Grandegger } 2491ca56202SWolfgang Grandegger 250676ae068SLucas Stach int ehci_hcd_stop(int index) 2511ca56202SWolfgang Grandegger { 2521ca56202SWolfgang Grandegger return 0; 2531ca56202SWolfgang Grandegger } 254