| /* | 
 |  * da8xx.c - TI's DA8xx platform specific usb wrapper functions. | 
 |  * | 
 |  * Author: Ajay Kumar Gupta <ajay.gupta@ti.com> | 
 |  * | 
 |  * Based on drivers/usb/musb/davinci.c | 
 |  * | 
 |  * Copyright (C) 2009 Texas Instruments Incorporated | 
 |  * | 
 |  * SPDX-License-Identifier:	GPL-2.0+ | 
 |  */ | 
 | #include <common.h> | 
 |  | 
 | #include "musb_core.h" | 
 | #include <asm/arch/da8xx-usb.h> | 
 |  | 
 | /* MUSB platform configuration */ | 
 | struct musb_config musb_cfg = { | 
 | 	.regs		= (struct musb_regs *)DA8XX_USB_OTG_CORE_BASE, | 
 | 	.timeout	= DA8XX_USB_OTG_TIMEOUT, | 
 | 	.musb_speed	= 0, | 
 | }; | 
 |  | 
 | /* | 
 |  * This function enables VBUS by driving the GPIO Bank4 Pin 15 high. | 
 |  */ | 
 | static void enable_vbus(void) | 
 | { | 
 | 	u32 value; | 
 |  | 
 | 	/* configure GPIO bank4 pin 15 in output direction */ | 
 | 	value = readl(&davinci_gpio_bank45->dir); | 
 | 	writel((value & (~DA8XX_USB_VBUS_GPIO)), &davinci_gpio_bank45->dir); | 
 |  | 
 | 	/* set GPIO bank4 pin 15 high to drive VBUS */ | 
 | 	value = readl(&davinci_gpio_bank45->set_data); | 
 | 	writel((value | DA8XX_USB_VBUS_GPIO), &davinci_gpio_bank45->set_data); | 
 | } | 
 |  | 
 | /* | 
 |  * Enable the usb0 phy. This initialization procedure is explained in | 
 |  * the DA8xx USB user guide document. | 
 |  */ | 
 | static u8 phy_on(void) | 
 | { | 
 | 	u32 timeout; | 
 | 	u32 cfgchip2; | 
 |  | 
 | 	cfgchip2 = readl(&davinci_syscfg_regs->cfgchip2); | 
 |  | 
 | 	cfgchip2 &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN | | 
 | 		      CFGCHIP2_OTGMODE | CFGCHIP2_REFFREQ); | 
 | 	cfgchip2 |= CFGCHIP2_SESENDEN | CFGCHIP2_VBDTCTEN | CFGCHIP2_PHY_PLLON | | 
 | 		    CFGCHIP2_REFFREQ_24MHZ; | 
 |  | 
 | 	writel(cfgchip2, &davinci_syscfg_regs->cfgchip2); | 
 |  | 
 | 	/* wait until the usb phy pll locks */ | 
 | 	timeout = musb_cfg.timeout; | 
 | 	while (timeout--) | 
 | 		if (readl(&davinci_syscfg_regs->cfgchip2) & CFGCHIP2_PHYCLKGD) | 
 | 			return 1; | 
 |  | 
 | 	/* USB phy was not turned on */ | 
 | 	return 0; | 
 | } | 
 |  | 
 | /* | 
 |  * Disable the usb phy | 
 |  */ | 
 | static void phy_off(void) | 
 | { | 
 | 	u32 cfgchip2; | 
 |  | 
 | 	/* | 
 | 	 * Power down the on-chip PHY. | 
 | 	 */ | 
 | 	cfgchip2 = readl(&davinci_syscfg_regs->cfgchip2); | 
 | 	cfgchip2 &= ~CFGCHIP2_PHY_PLLON; | 
 | 	cfgchip2 |= CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN; | 
 | 	writel(cfgchip2, &davinci_syscfg_regs->cfgchip2); | 
 | } | 
 |  | 
 | /* | 
 |  * This function performs DA8xx platform specific initialization for usb0. | 
 |  */ | 
 | int musb_platform_init(void) | 
 | { | 
 | 	u32  revision; | 
 |  | 
 | 	/* enable psc for usb2.0 */ | 
 | 	lpsc_on(33); | 
 |  | 
 | 	/* enable usb vbus */ | 
 | 	enable_vbus(); | 
 |  | 
 | 	/* reset the controller */ | 
 | 	writel(0x1, &da8xx_usb_regs->control); | 
 | 	udelay(5000); | 
 |  | 
 | 	/* start the on-chip usb phy and its pll */ | 
 | 	if (phy_on() == 0) | 
 | 		return -1; | 
 |  | 
 | 	/* Returns zero if e.g. not clocked */ | 
 | 	revision = readl(&da8xx_usb_regs->revision); | 
 | 	if (revision == 0) | 
 | 		return -1; | 
 |  | 
 | 	/* Disable all interrupts */ | 
 | 	writel((DA8XX_USB_USBINT_MASK | DA8XX_USB_TXINT_MASK | | 
 | 		DA8XX_USB_RXINT_MASK), &da8xx_usb_regs->intmsk_set); | 
 | 	return 0; | 
 | } | 
 |  | 
 | /* | 
 |  * This function performs DA8xx platform specific deinitialization for usb0. | 
 |  */ | 
 | void musb_platform_deinit(void) | 
 | { | 
 | 	/* Turn of the phy */ | 
 | 	phy_off(); | 
 |  | 
 | 	/* flush any interrupts */ | 
 | 	writel((DA8XX_USB_USBINT_MASK | DA8XX_USB_TXINT_MASK | | 
 | 		DA8XX_USB_RXINT_MASK), &da8xx_usb_regs->intmsk_clr); | 
 | 	writel(0, &da8xx_usb_regs->eoi); | 
 | } |