/* linux/drivers/usb/phy/phy-samsung-usb.c
 *
 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
 *              http://www.samsung.com
 *
 * Author: Praveen Paneri <p.paneri@samsung.com>
 *
 * Samsung USB-PHY helper driver with common function calls;
 * interacts with Samsung USB 2.0 PHY controller driver and later
 * with Samsung USB 3.0 PHY driver.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * 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.
 */

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/usb/samsung_usb_phy.h>

#include "phy-samsung-usb.h"

int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy)
{
	struct device_node *usbphy_sys;
	struct device_node *node = sphy->dev->of_node;

	/* Get the Channel number in case of multiple PHY controllers */
	sphy->channel = of_alias_get_id(node, "usb3phy");
	if (sphy->channel < 0)
		dev_info(sphy->dev, "Not a multi controller PHY\n");

	/* Getting node for system controller interface for usb-phy */
	usbphy_sys = of_get_child_by_name(node, "usbphy-sys");
	if (!usbphy_sys) {
		dev_err(sphy->dev, "No sys-controller interface for usb-phy\n");
		return -ENODEV;
	}

	sphy->pmuregs = of_iomap(usbphy_sys, 0);

	if (sphy->pmuregs == NULL) {
		dev_err(sphy->dev, "Can't get usb-phy pmu control register\n");
		goto err0;
	}

	sphy->sysreg = of_iomap(usbphy_sys, 1);

	/*
	 * Not returning error code here, since this situation is not fatal.
	 * Few SoCs may not have this switch available
	 */
	if (sphy->sysreg == NULL)
		dev_warn(sphy->dev, "Can't get usb-phy sysreg cfg register\n");

	of_node_put(usbphy_sys);

	return 0;

err0:
	of_node_put(usbphy_sys);
	return -ENXIO;
}
EXPORT_SYMBOL_GPL(samsung_usbphy_parse_dt);

/*
 * Set isolation here for phy.
 * Here 'on = true' would mean USB PHY block is isolated, hence
 * de-activated and vice-versa.
 */
void samsung_usbphy_set_isolation_4210(struct samsung_usbphy *sphy, bool on)
{
	void __iomem *reg = NULL;
	u32 reg_val;
	u32 en_mask = 0;

	if (!sphy->pmuregs) {
		dev_warn(sphy->dev, "Can't set pmu isolation\n");
		return;
	}

	if (sphy->phy_type == USB_PHY_TYPE_DEVICE) {
		if (sphy->channel == 1)
			reg = sphy->pmuregs +
				sphy->drv_data->dev1_phy_reg_offset;
		else
			reg = sphy->pmuregs +
				sphy->drv_data->dev0_phy_reg_offset;
		en_mask = sphy->drv_data->devphy_en_mask;
	} else if (sphy->phy_type == USB_PHY_TYPE_HOST) {
		reg = sphy->pmuregs + sphy->drv_data->hostphy_reg_offset;
		en_mask = sphy->drv_data->hostphy_en_mask;
	}

	if (reg) {
		reg_val = readl(reg);
		if (on)
			reg_val &= ~en_mask;
		else
			reg_val |= en_mask;
		writel(reg_val, reg);
	}

	if (sphy->drv_data->cpu_type == TYPE_EXYNOS4X12) {
		writel(reg_val, sphy->pmuregs + EXYNOS4X12_PHY_HSIC_CTRL0);
		writel(reg_val, sphy->pmuregs + EXYNOS4X12_PHY_HSIC_CTRL1);
	}
}
EXPORT_SYMBOL_GPL(samsung_usbphy_set_isolation_4210);

/*
 * Configure the mode of working of usb-phy here: HOST/DEVICE.
 */
void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy)
{
	u32 reg;

	if (!sphy->sysreg) {
		dev_warn(sphy->dev, "Can't configure specified phy mode\n");
		return;
	}

	reg = readl(sphy->sysreg);

	if (sphy->phy_type == USB_PHY_TYPE_DEVICE)
		reg &= ~EXYNOS_USB20PHY_CFG_HOST_LINK;
	else if (sphy->phy_type == USB_PHY_TYPE_HOST)
		reg |= EXYNOS_USB20PHY_CFG_HOST_LINK;

	writel(reg, sphy->sysreg);
}
EXPORT_SYMBOL_GPL(samsung_usbphy_cfg_sel);

/*
 * PHYs are different for USB Device and USB Host.
 * This make sure that correct PHY type is selected before
 * any operation on PHY.
 */
int samsung_usbphy_set_type(struct usb_phy *phy,
				enum samsung_usb_phy_type phy_type)
{
	struct samsung_usbphy *sphy = phy_to_sphy(phy);

	sphy->phy_type = phy_type;

	return 0;
}
EXPORT_SYMBOL_GPL(samsung_usbphy_set_type);

int samsung_usbphy_rate_to_clksel_64xx(struct samsung_usbphy *sphy,
							unsigned long rate)
{
	unsigned int clksel;

	switch (rate) {
	case 12 * MHZ:
		clksel = PHYCLK_CLKSEL_12M;
		break;
	case 24 * MHZ:
		clksel = PHYCLK_CLKSEL_24M;
		break;
	case 48 * MHZ:
		clksel = PHYCLK_CLKSEL_48M;
		break;
	default:
		dev_err(sphy->dev,
			"Invalid reference clock frequency: %lu\n", rate);
		return -EINVAL;
	}

	return clksel;
}
EXPORT_SYMBOL_GPL(samsung_usbphy_rate_to_clksel_64xx);

int samsung_usbphy_rate_to_clksel_4x12(struct samsung_usbphy *sphy,
							unsigned long rate)
{
	unsigned int clksel;

	switch (rate) {
	case 9600 * KHZ:
		clksel = FSEL_CLKSEL_9600K;
		break;
	case 10 * MHZ:
		clksel = FSEL_CLKSEL_10M;
		break;
	case 12 * MHZ:
		clksel = FSEL_CLKSEL_12M;
		break;
	case 19200 * KHZ:
		clksel = FSEL_CLKSEL_19200K;
		break;
	case 20 * MHZ:
		clksel = FSEL_CLKSEL_20M;
		break;
	case 24 * MHZ:
		clksel = FSEL_CLKSEL_24M;
		break;
	case 50 * MHZ:
		clksel = FSEL_CLKSEL_50M;
		break;
	default:
		dev_err(sphy->dev,
			"Invalid reference clock frequency: %lu\n", rate);
		return -EINVAL;
	}

	return clksel;
}
EXPORT_SYMBOL_GPL(samsung_usbphy_rate_to_clksel_4x12);

/*
 * Returns reference clock frequency selection value
 */
int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
{
	struct clk *ref_clk;
	unsigned long rate;
	int refclk_freq;
	int cpu_type = sphy->drv_data->cpu_type;

	/*
	 * In exynos5250 USB host and device PHY use
	 * external crystal clock XXTI
	 */
	switch (cpu_type) {
	case TYPE_EXYNOS5420:
		/* fall through */
	case TYPE_EXYNOS5250:
		ref_clk = clk_get(sphy->dev, "ext_xtal");
		break;
	case TYPE_EXYNOS4210:
		/* fall through */
	case TYPE_S3C64XX:
		ref_clk = clk_get(sphy->dev, "xusbxti");
		break;
	default:
		break;
	}

	if (IS_ERR(ref_clk)) {
		dev_err(sphy->dev, "Failed to get reference clock\n");
		return PTR_ERR(ref_clk);
	}

	rate = clk_get_rate(ref_clk);
	refclk_freq = sphy->drv_data->rate_to_clksel(sphy, rate);

	clk_put(ref_clk);

	return refclk_freq;
}
EXPORT_SYMBOL_GPL(samsung_usbphy_get_refclk_freq);
