| 
									
										
										
										
											2010-12-10 17:58:20 +05:30
										 |  |  | /*
 | 
					
						
							|  |  |  |   * This file configures the internal USB PHY in OMAP4430. Used | 
					
						
							|  |  |  |   * with TWL6030 transceiver and MUSB on OMAP4430. | 
					
						
							|  |  |  |   * | 
					
						
							|  |  |  |   * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
 | 
					
						
							|  |  |  |   * This program is free software; you can redistribute it and/or modify | 
					
						
							|  |  |  |   * it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  |   * the Free Software Foundation; either version 2 of the License, or | 
					
						
							|  |  |  |   * (at your option) any later version. | 
					
						
							|  |  |  |   * | 
					
						
							|  |  |  |   * Author: Hema HK <hemahk@ti.com> | 
					
						
							|  |  |  |   * | 
					
						
							|  |  |  |   * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |   * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |   * GNU General Public License for more details. | 
					
						
							|  |  |  |   * | 
					
						
							|  |  |  |   * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |   * along with this program; if not, write to the Free Software | 
					
						
							|  |  |  |   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 
					
						
							|  |  |  |   * | 
					
						
							|  |  |  |   */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <linux/types.h>
 | 
					
						
							|  |  |  | #include <linux/delay.h>
 | 
					
						
							|  |  |  | #include <linux/clk.h>
 | 
					
						
							|  |  |  | #include <linux/io.h>
 | 
					
						
							|  |  |  | #include <linux/err.h>
 | 
					
						
							|  |  |  | #include <linux/usb.h>
 | 
					
						
							| 
									
										
										
										
											2012-10-24 14:26:18 -07:00
										 |  |  | #include <linux/usb/musb.h>
 | 
					
						
							| 
									
										
										
										
											2012-08-27 17:43:01 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-31 10:59:07 -07:00
										 |  |  | #include "soc.h"
 | 
					
						
							| 
									
										
										
										
											2011-02-16 17:34:40 +05:30
										 |  |  | #include "control.h"
 | 
					
						
							| 
									
										
										
										
											2012-10-24 14:26:18 -07:00
										 |  |  | #include "usb.h"
 | 
					
						
							| 
									
										
										
										
											2010-12-10 17:58:20 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-09 16:30:35 +02:00
										 |  |  | #define CONTROL_DEV_CONF		0x300
 | 
					
						
							|  |  |  | #define PHY_PD				0x1
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * omap4430_phy_power_down: disable MUSB PHY during early init | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * OMAP4 MUSB PHY module is enabled by default on reset, but this will | 
					
						
							|  |  |  |  * prevent core retention if not disabled by SW. USB driver will | 
					
						
							|  |  |  |  * later on enable this, once and if the driver needs it. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int __init omap4430_phy_power_down(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	void __iomem *ctrl_base; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!cpu_is_omap44xx()) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ctrl_base = ioremap(OMAP443X_SCM_BASE, SZ_1K); | 
					
						
							|  |  |  | 	if (!ctrl_base) { | 
					
						
							|  |  |  | 		pr_err("control module ioremap failed\n"); | 
					
						
							|  |  |  | 		return -ENOMEM; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Power down the phy */ | 
					
						
							| 
									
										
										
										
											2014-04-15 20:37:46 +03:00
										 |  |  | 	writel_relaxed(PHY_PD, ctrl_base + CONTROL_DEV_CONF); | 
					
						
							| 
									
										
										
										
											2012-11-09 16:30:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	iounmap(ctrl_base); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-01-11 11:24:18 -08:00
										 |  |  | omap_early_initcall(omap4430_phy_power_down); | 
					
						
							| 
									
										
										
										
											2012-11-09 16:30:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-16 17:34:40 +05:30
										 |  |  | void am35x_musb_reset(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	u32	regval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Reset the musb interface */ | 
					
						
							|  |  |  | 	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	regval |= AM35XX_USBOTGSS_SW_RST; | 
					
						
							|  |  |  | 	omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	regval &= ~AM35XX_USBOTGSS_SW_RST; | 
					
						
							|  |  |  | 	omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void am35x_musb_phy_power(u8 on) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned long timeout = jiffies + msecs_to_jiffies(100); | 
					
						
							|  |  |  | 	u32 devconf2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (on) { | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * Start the on-chip PHY and its PLL. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN); | 
					
						
							|  |  |  | 		devconf2 |= CONF2_PHY_PLLON; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		pr_info(KERN_INFO "Waiting for PHY clock good...\n"); | 
					
						
							|  |  |  | 		while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2) | 
					
						
							|  |  |  | 				& CONF2_PHYCLKGD)) { | 
					
						
							|  |  |  | 			cpu_relax(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (time_after(jiffies, timeout)) { | 
					
						
							|  |  |  | 				pr_err(KERN_ERR "musb PHY clock good timed out\n"); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * Power down the on-chip PHY. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		devconf2 &= ~CONF2_PHY_PLLON; | 
					
						
							|  |  |  | 		devconf2 |=  CONF2_PHYPWRDN | CONF2_OTGPWRDN; | 
					
						
							|  |  |  | 		omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void am35x_musb_clear_irq(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	u32 regval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); | 
					
						
							|  |  |  | 	regval |= AM35XX_USBOTGSS_INT_CLR; | 
					
						
							|  |  |  | 	omap_ctrl_writel(regval, AM35XX_CONTROL_LVL_INTR_CLEAR); | 
					
						
							|  |  |  | 	regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-02 12:45:05 +03:00
										 |  |  | void am35x_set_mode(u8 musb_mode) | 
					
						
							| 
									
										
										
										
											2011-02-16 17:34:40 +05:30
										 |  |  | { | 
					
						
							|  |  |  | 	u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	devconf2 &= ~CONF2_OTGMODE; | 
					
						
							|  |  |  | 	switch (musb_mode) { | 
					
						
							|  |  |  | 	case MUSB_HOST:		/* Force VBUS valid, ID = 0 */ | 
					
						
							|  |  |  | 		devconf2 |= CONF2_FORCE_HOST; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case MUSB_PERIPHERAL:	/* Force VBUS valid, ID = 1 */ | 
					
						
							|  |  |  | 		devconf2 |= CONF2_FORCE_DEVICE; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case MUSB_OTG:		/* Don't override the VBUS/ID comparators */ | 
					
						
							|  |  |  | 		devconf2 |= CONF2_NO_OVERRIDE; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		pr_info(KERN_INFO "Unsupported mode %u\n", musb_mode); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-12-13 10:50:58 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | void ti81xx_musb_phy_power(u8 on) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	void __iomem *scm_base = NULL; | 
					
						
							|  |  |  | 	u32 usbphycfg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	scm_base = ioremap(TI81XX_SCM_BASE, SZ_2K); | 
					
						
							|  |  |  | 	if (!scm_base) { | 
					
						
							|  |  |  | 		pr_err("system control module ioremap failed\n"); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-15 20:37:46 +03:00
										 |  |  | 	usbphycfg = readl_relaxed(scm_base + USBCTRL0); | 
					
						
							| 
									
										
										
										
											2011-12-13 10:50:58 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (on) { | 
					
						
							|  |  |  | 		if (cpu_is_ti816x()) { | 
					
						
							|  |  |  | 			usbphycfg |= TI816X_USBPHY0_NORMAL_MODE; | 
					
						
							|  |  |  | 			usbphycfg &= ~TI816X_USBPHY_REFCLK_OSC; | 
					
						
							|  |  |  | 		} else if (cpu_is_ti814x()) { | 
					
						
							|  |  |  | 			usbphycfg &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN | 
					
						
							|  |  |  | 				| USBPHY_DPINPUT | USBPHY_DMINPUT); | 
					
						
							|  |  |  | 			usbphycfg |= (USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN | 
					
						
							|  |  |  | 				| USBPHY_DPOPBUFCTL | USBPHY_DMOPBUFCTL); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		if (cpu_is_ti816x()) | 
					
						
							|  |  |  | 			usbphycfg &= ~TI816X_USBPHY0_NORMAL_MODE; | 
					
						
							|  |  |  | 		else if (cpu_is_ti814x()) | 
					
						
							|  |  |  | 			usbphycfg |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-04-15 20:37:46 +03:00
										 |  |  | 	writel_relaxed(usbphycfg, scm_base + USBCTRL0); | 
					
						
							| 
									
										
										
										
											2011-12-13 10:50:58 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	iounmap(scm_base); | 
					
						
							|  |  |  | } |