/*
  * 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>
#include <linux/usb/musb.h>

#include "soc.h"
#include "control.h"
#include "usb.h"

#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 */
	writel_relaxed(PHY_PD, ctrl_base + CONTROL_DEV_CONF);

	iounmap(ctrl_base);

	return 0;
}
omap_early_initcall(omap4430_phy_power_down);

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);
}

void am35x_set_mode(u8 musb_mode)
{
	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);
}

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;
	}

	usbphycfg = readl_relaxed(scm_base + USBCTRL0);

	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;

	}
	writel_relaxed(usbphycfg, scm_base + USBCTRL0);

	iounmap(scm_base);
}
