/*
 * Copyright (C) 2010 Michael Grzeschik <mgr@pengutronix.de>
 *
 * This file is released under the GPLv2
 *
 */

/*
 * OMAP USBHOST Register addresses: VIRTUAL ADDRESSES
 */

/*-------------------------------------------------------------------------*/

#include <mfd/twl4030.h>
#include <usb/twl4030.h>
#include <mach/ehci.h>
#include <common.h>
#include <asm/io.h>
#include <clock.h>
#include <gpio.h>
#include <mach/omap3-silicon.h>
#include <mach/omap3-clock.h>
#include <mach/cm-regbits-34xx.h>
#include <mach/sys_info.h>

void omap_usb_utmi_init(struct omap_hcd *omap, u8 tll_channel_mask)
{
	unsigned reg;
	int i;

	/* Program the 3 TLL channels upfront */
	for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) {
		reg = __raw_readl(OMAP_USBTLL_BASE + OMAP_TLL_CHANNEL_CONF(i));

		/* Disable AutoIdle, BitStuffing and use SDR Mode */
		reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE
				| OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF
				| OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE);
		__raw_writel(reg, OMAP_USBTLL_BASE + OMAP_TLL_CHANNEL_CONF(i));
	}

	/* Program Common TLL register */
	reg = __raw_readl(OMAP_USBTLL_BASE + OMAP_TLL_SHARED_CONF);
	reg |= (OMAP_TLL_SHARED_CONF_FCLK_IS_ON
			| OMAP_TLL_SHARED_CONF_USB_DIVRATION
			| OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN);
	reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN;

	__raw_writel(reg, OMAP_USBTLL_BASE + OMAP_TLL_SHARED_CONF);

	/* Enable channels now */
	for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) {
		reg = __raw_readl(OMAP_USBTLL_BASE + OMAP_TLL_CHANNEL_CONF(i));

		/* Enable only the reg that is needed */
		if (!(tll_channel_mask & 1<<i))
			continue;

		reg |= OMAP_TLL_CHANNEL_CONF_CHANEN;
		__raw_writel(reg, OMAP_USBTLL_BASE + OMAP_TLL_CHANNEL_CONF(i));

		__raw_writeb(0xbe,
			OMAP_USBTLL_BASE + OMAP_TLL_ULPI_SCRATCH_REGISTER(i));
	}
}

int ehci_omap_init(struct omap_hcd *omap)
{
	uint64_t start;
	int timeout = 1000;
	u8 tll_ch_mask = 0;
	u32 v = 0;

	if (twl4030_usb_ulpi_init()) {
		printf("ERROR: %s Could not initialize PHY\n",
			__PRETTY_FUNCTION__);
		return -EINVAL;
	}


	v = __raw_readl(CM_REG(CLKSEL4_PLL));
	v |= (12 << OMAP3430ES2_PERIPH2_DPLL_DIV_SHIFT);
	v |= (120 << OMAP3430ES2_PERIPH2_DPLL_MULT_SHIFT);
	__raw_writel(v, CM_REG(CLKSEL4_PLL));

	v = __raw_readl(CM_REG(CLKSEL5_PLL));
	v |= (1 << OMAP3430ES2_DIV_120M_SHIFT);
	__raw_writel(v, CM_REG(CLKSEL5_PLL));

	v = __raw_readl(CM_REG(CLKEN2_PLL));
	v |= (7 << OMAP3430ES2_PERIPH2_DPLL_FREQSEL_SHIFT);
	v |= (7 << OMAP3430ES2_EN_PERIPH2_DPLL_SHIFT);
	__raw_writel(v, CM_REG(CLKEN2_PLL));

	/* PRCM settings for USBHOST:
	* Interface clk un-related to domain transition
	*/

	v = __raw_readl(CM_REG(AIDLE_USBH));
	v |= (0 << OMAP3430ES2_AUTO_USBHOST_SHIFT);
	__raw_writel(v, CM_REG(AIDLE_USBH));

        /* Disable sleep dependency with MPU and IVA */

	v = __raw_readl(CM_REG(SLEEPD_USBH));
	v |= (0 << OMAP3430ES2_EN_MPU_SHIFT);
	v |= (0 << OMAP3430ES2_EN_IVA2_SHIFT);
	__raw_writel(v, CM_REG(SLEEPD_USBH));

	/* Disable Automatic transition of clock */
	v = __raw_readl(CM_REG(CLKSTCTRL_USBH));
	v |= (0 << OMAP3430ES2_CLKTRCTRL_USBHOST_SHIFT);
	__raw_writel(v, CM_REG(CLKSTCTRL_USBH));

	/* Enable Clocks for USBHOST */

	/* enable usbhost_ick */
	v = __raw_readl(CM_REG(ICLKEN_USBH));
	v |= (1 << OMAP3430ES2_EN_USBHOST_SHIFT);
	__raw_writel(v, CM_REG(ICLKEN_USBH));

	/* enable usbhost_120m_fck */
	v = __raw_readl(CM_REG(FCLKEN_USBH));
	v |= (1 << OMAP3430ES2_EN_USBHOST2_SHIFT);
	__raw_writel(v, CM_REG(FCLKEN_USBH));

	/* enable usbhost_48m_fck */
	v = __raw_readl(CM_REG(FCLKEN_USBH));
	v |= (1 << OMAP3430ES2_EN_USBHOST1_SHIFT);
	__raw_writel(v, CM_REG(FCLKEN_USBH));

	if (omap->phy_reset) {
		/* Refer: ISSUE1 */
		if (omap->reset_gpio_port[0] != -EINVAL) {
			gpio_direction_output(omap->reset_gpio_port[0], 0);
		}

		if (omap->reset_gpio_port[1] != -EINVAL) {
			gpio_direction_output(omap->reset_gpio_port[1], 0);
		}

		/* Hold the PHY in RESET for enough time till DIR is high */
		mdelay(10);
	}

	/* enable usbtll_fck  */
	v = __raw_readl(CM_REG(FCLKEN3_CORE));
	v |= (1 << OMAP3430ES2_EN_USBTLL_SHIFT);
	__raw_writel(v, CM_REG(FCLKEN3_CORE));

	/* Configure TLL for 60Mhz clk for ULPI */
	/* enable usbtll_ick */
	v = __raw_readl(CM_REG(ICLKEN3_CORE));
	v |= (1 << OMAP3430ES2_EN_USBTLL_SHIFT);
	__raw_writel(v, CM_REG(ICLKEN3_CORE));

	v = __raw_readl(CM_REG(AIDLE3_CORE));
	v |= (0 << OMAP3430ES2_AUTO_USBTLL_SHIFT);
	__raw_writel(v, CM_REG(AIDLE3_CORE));

	/* perform TLL soft reset, and wait until reset is complete */
	__raw_writel(OMAP_USBTLL_SYSCONFIG_SOFTRESET,
				OMAP_USBTLL_BASE + OMAP_USBTLL_SYSCONFIG);

	/* Wait for TLL reset to complete */
	start = get_time_ns();

	while (!(__raw_readl(OMAP_USBTLL_BASE + OMAP_USBTLL_SYSSTATUS)
			& OMAP_USBTLL_SYSSTATUS_RESETDONE)) {
		if (is_timeout(start, timeout * USECOND)) {
			return -ETIMEDOUT;
		}
	}

	/* (1<<3) = no idle mode only for initial debugging */
	__raw_writel(OMAP_USBTLL_SYSCONFIG_ENAWAKEUP |
			OMAP_USBTLL_SYSCONFIG_SIDLEMODE |
			OMAP_USBTLL_SYSCONFIG_CACTIVITY, OMAP_USBTLL_BASE + OMAP_USBTLL_SYSCONFIG);

	/* Put UHH in NoIdle/NoStandby mode */
	v = __raw_readl(OMAP_UHH_CONFIG_BASE + OMAP_UHH_SYSCONFIG);
	v |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP
			| OMAP_UHH_SYSCONFIG_SIDLEMODE
			| OMAP_UHH_SYSCONFIG_CACTIVITY
			| OMAP_UHH_SYSCONFIG_MIDLEMODE);
	v &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE;
	__raw_writel(v, OMAP_UHH_CONFIG_BASE + OMAP_UHH_SYSCONFIG);

	v = __raw_readl(OMAP_UHH_CONFIG_BASE + OMAP_UHH_HOSTCONFIG);
	/* setup ULPI bypass and burst configurations */
	v |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
			| OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN
			| OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN);
	v &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN;

	if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN)
		v &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS;
	if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN)
		v &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS;
	if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN)
		v &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS;

	/* Bypass the TLL module for PHY mode operation */
	 if (get_cpu_rev() <= OMAP34XX_ES2_1) {
		if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) ||
			(omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) ||
				(omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY))
			v &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
		else
			v |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
	} else {
		if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY)
			v &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
		else if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL)
			v |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;

		if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY)
			v &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
		else if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL)
			v |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;

		if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY)
			v &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;
		else if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)
			v |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;

	}
	__raw_writel(v, OMAP_UHH_CONFIG_BASE + OMAP_UHH_HOSTCONFIG);

	if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) ||
		(omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) ||
			(omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)) {

		if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL)
			tll_ch_mask |= OMAP_TLL_CHANNEL_1_EN_MASK;
		if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL)
			tll_ch_mask |= OMAP_TLL_CHANNEL_2_EN_MASK;
		if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)
			tll_ch_mask |= OMAP_TLL_CHANNEL_3_EN_MASK;

		/* Enable UTMI mode for required TLL channels */
		omap_usb_utmi_init(omap, tll_ch_mask);
	}

	if (omap->phy_reset) {
		/* Refer ISSUE1:
		 * Hold the PHY in RESET for enough time till
		 * PHY is settled and ready
		 */
		udelay(10);

		if (omap->reset_gpio_port[0] != -EINVAL)
			gpio_direction_output(omap->reset_gpio_port[0], 1);

		if (omap->reset_gpio_port[1] != -EINVAL)
			gpio_direction_output(omap->reset_gpio_port[1], 1);
	}

	return 0;
}
