1 /* 2 * This file configures the internal USB PHY in OMAP4430. Used 3 * with TWL6030 transceiver and MUSB on OMAP4430. 4 * 5 * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * Author: Hema HK <hemahk@ti.com> 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 * 22 */ 23 24 #include <linux/types.h> 25 #include <linux/delay.h> 26 #include <linux/clk.h> 27 #include <linux/io.h> 28 #include <linux/err.h> 29 #include <linux/usb.h> 30 31 #include <plat/usb.h> 32 33 #include "soc.h" 34 #include "control.h" 35 36 void am35x_musb_reset(void) 37 { 38 u32 regval; 39 40 /* Reset the musb interface */ 41 regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); 42 43 regval |= AM35XX_USBOTGSS_SW_RST; 44 omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET); 45 46 regval &= ~AM35XX_USBOTGSS_SW_RST; 47 omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET); 48 49 regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); 50 } 51 52 void am35x_musb_phy_power(u8 on) 53 { 54 unsigned long timeout = jiffies + msecs_to_jiffies(100); 55 u32 devconf2; 56 57 if (on) { 58 /* 59 * Start the on-chip PHY and its PLL. 60 */ 61 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); 62 63 devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN); 64 devconf2 |= CONF2_PHY_PLLON; 65 66 omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); 67 68 pr_info(KERN_INFO "Waiting for PHY clock good...\n"); 69 while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2) 70 & CONF2_PHYCLKGD)) { 71 cpu_relax(); 72 73 if (time_after(jiffies, timeout)) { 74 pr_err(KERN_ERR "musb PHY clock good timed out\n"); 75 break; 76 } 77 } 78 } else { 79 /* 80 * Power down the on-chip PHY. 81 */ 82 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); 83 84 devconf2 &= ~CONF2_PHY_PLLON; 85 devconf2 |= CONF2_PHYPWRDN | CONF2_OTGPWRDN; 86 omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); 87 } 88 } 89 90 void am35x_musb_clear_irq(void) 91 { 92 u32 regval; 93 94 regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); 95 regval |= AM35XX_USBOTGSS_INT_CLR; 96 omap_ctrl_writel(regval, AM35XX_CONTROL_LVL_INTR_CLEAR); 97 regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); 98 } 99 100 void am35x_set_mode(u8 musb_mode) 101 { 102 u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); 103 104 devconf2 &= ~CONF2_OTGMODE; 105 switch (musb_mode) { 106 case MUSB_HOST: /* Force VBUS valid, ID = 0 */ 107 devconf2 |= CONF2_FORCE_HOST; 108 break; 109 case MUSB_PERIPHERAL: /* Force VBUS valid, ID = 1 */ 110 devconf2 |= CONF2_FORCE_DEVICE; 111 break; 112 case MUSB_OTG: /* Don't override the VBUS/ID comparators */ 113 devconf2 |= CONF2_NO_OVERRIDE; 114 break; 115 default: 116 pr_info(KERN_INFO "Unsupported mode %u\n", musb_mode); 117 } 118 119 omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); 120 } 121 122 void ti81xx_musb_phy_power(u8 on) 123 { 124 void __iomem *scm_base = NULL; 125 u32 usbphycfg; 126 127 scm_base = ioremap(TI81XX_SCM_BASE, SZ_2K); 128 if (!scm_base) { 129 pr_err("system control module ioremap failed\n"); 130 return; 131 } 132 133 usbphycfg = __raw_readl(scm_base + USBCTRL0); 134 135 if (on) { 136 if (cpu_is_ti816x()) { 137 usbphycfg |= TI816X_USBPHY0_NORMAL_MODE; 138 usbphycfg &= ~TI816X_USBPHY_REFCLK_OSC; 139 } else if (cpu_is_ti814x()) { 140 usbphycfg &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN 141 | USBPHY_DPINPUT | USBPHY_DMINPUT); 142 usbphycfg |= (USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN 143 | USBPHY_DPOPBUFCTL | USBPHY_DMOPBUFCTL); 144 } 145 } else { 146 if (cpu_is_ti816x()) 147 usbphycfg &= ~TI816X_USBPHY0_NORMAL_MODE; 148 else if (cpu_is_ti814x()) 149 usbphycfg |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN; 150 151 } 152 __raw_writel(usbphycfg, scm_base + USBCTRL0); 153 154 iounmap(scm_base); 155 } 156