/*
 * Samsung SoC USB 1.1/2.0 PHY driver
 *
 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
 * Author: Kamil Debski <k.debski@samsung.com>
 *
 * 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.
 */

#include <linux/clk.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include "phy-samsung-usb2.h"

static int samsung_usb2_phy_power_on(struct phy *phy)
{
	struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy);
	struct samsung_usb2_phy_driver *drv = inst->drv;
	int ret;

	dev_dbg(drv->dev, "Request to power_on \"%s\" usb phy\n",
		inst->cfg->label);

	if (drv->vbus) {
		ret = regulator_enable(drv->vbus);
		if (ret)
			goto err_regulator;
	}

	ret = clk_prepare_enable(drv->clk);
	if (ret)
		goto err_main_clk;
	ret = clk_prepare_enable(drv->ref_clk);
	if (ret)
		goto err_instance_clk;
	if (inst->cfg->power_on) {
		spin_lock(&drv->lock);
		ret = inst->cfg->power_on(inst);
		spin_unlock(&drv->lock);
		if (ret)
			goto err_power_on;
	}

	return 0;

err_power_on:
	clk_disable_unprepare(drv->ref_clk);
err_instance_clk:
	clk_disable_unprepare(drv->clk);
err_main_clk:
	if (drv->vbus)
		regulator_disable(drv->vbus);
err_regulator:
	return ret;
}

static int samsung_usb2_phy_power_off(struct phy *phy)
{
	struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy);
	struct samsung_usb2_phy_driver *drv = inst->drv;
	int ret = 0;

	dev_dbg(drv->dev, "Request to power_off \"%s\" usb phy\n",
		inst->cfg->label);
	if (inst->cfg->power_off) {
		spin_lock(&drv->lock);
		ret = inst->cfg->power_off(inst);
		spin_unlock(&drv->lock);
		if (ret)
			return ret;
	}
	clk_disable_unprepare(drv->ref_clk);
	clk_disable_unprepare(drv->clk);
	if (drv->vbus)
		ret = regulator_disable(drv->vbus);

	return ret;
}

static const struct phy_ops samsung_usb2_phy_ops = {
	.power_on	= samsung_usb2_phy_power_on,
	.power_off	= samsung_usb2_phy_power_off,
	.owner		= THIS_MODULE,
};

static struct phy *samsung_usb2_phy_xlate(struct device *dev,
					struct of_phandle_args *args)
{
	struct samsung_usb2_phy_driver *drv;

	drv = dev_get_drvdata(dev);
	if (!drv)
		return ERR_PTR(-EINVAL);

	if (WARN_ON(args->args[0] >= drv->cfg->num_phys))
		return ERR_PTR(-ENODEV);

	return drv->instances[args->args[0]].phy;
}

static const struct of_device_id samsung_usb2_phy_of_match[] = {
#ifdef CONFIG_PHY_EXYNOS4X12_USB2
	{
		.compatible = "samsung,exynos3250-usb2-phy",
		.data = &exynos3250_usb2_phy_config,
	},
#endif
#ifdef CONFIG_PHY_EXYNOS4210_USB2
	{
		.compatible = "samsung,exynos4210-usb2-phy",
		.data = &exynos4210_usb2_phy_config,
	},
#endif
#ifdef CONFIG_PHY_EXYNOS4X12_USB2
	{
		.compatible = "samsung,exynos4x12-usb2-phy",
		.data = &exynos4x12_usb2_phy_config,
	},
#endif
#ifdef CONFIG_PHY_EXYNOS5250_USB2
	{
		.compatible = "samsung,exynos5250-usb2-phy",
		.data = &exynos5250_usb2_phy_config,
	},
#endif
#ifdef CONFIG_PHY_S5PV210_USB2
	{
		.compatible = "samsung,s5pv210-usb2-phy",
		.data = &s5pv210_usb2_phy_config,
	},
#endif
	{ },
};
MODULE_DEVICE_TABLE(of, samsung_usb2_phy_of_match);

static int samsung_usb2_phy_probe(struct platform_device *pdev)
{
	const struct of_device_id *match;
	const struct samsung_usb2_phy_config *cfg;
	struct device *dev = &pdev->dev;
	struct phy_provider *phy_provider;
	struct resource *mem;
	struct samsung_usb2_phy_driver *drv;
	int i, ret;

	if (!pdev->dev.of_node) {
		dev_err(dev, "This driver is required to be instantiated from device tree\n");
		return -EINVAL;
	}

	match = of_match_node(samsung_usb2_phy_of_match, pdev->dev.of_node);
	if (!match) {
		dev_err(dev, "of_match_node() failed\n");
		return -EINVAL;
	}
	cfg = match->data;

	drv = devm_kzalloc(dev, sizeof(struct samsung_usb2_phy_driver) +
		cfg->num_phys * sizeof(struct samsung_usb2_phy_instance),
								GFP_KERNEL);
	if (!drv)
		return -ENOMEM;

	dev_set_drvdata(dev, drv);
	spin_lock_init(&drv->lock);

	drv->cfg = cfg;
	drv->dev = dev;

	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	drv->reg_phy = devm_ioremap_resource(dev, mem);
	if (IS_ERR(drv->reg_phy)) {
		dev_err(dev, "Failed to map register memory (phy)\n");
		return PTR_ERR(drv->reg_phy);
	}

	drv->reg_pmu = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
		"samsung,pmureg-phandle");
	if (IS_ERR(drv->reg_pmu)) {
		dev_err(dev, "Failed to map PMU registers (via syscon)\n");
		return PTR_ERR(drv->reg_pmu);
	}

	if (drv->cfg->has_mode_switch) {
		drv->reg_sys = syscon_regmap_lookup_by_phandle(
				pdev->dev.of_node, "samsung,sysreg-phandle");
		if (IS_ERR(drv->reg_sys)) {
			dev_err(dev, "Failed to map system registers (via syscon)\n");
			return PTR_ERR(drv->reg_sys);
		}
	}

	drv->clk = devm_clk_get(dev, "phy");
	if (IS_ERR(drv->clk)) {
		dev_err(dev, "Failed to get clock of phy controller\n");
		return PTR_ERR(drv->clk);
	}

	drv->ref_clk = devm_clk_get(dev, "ref");
	if (IS_ERR(drv->ref_clk)) {
		dev_err(dev, "Failed to get reference clock for the phy controller\n");
		return PTR_ERR(drv->ref_clk);
	}

	drv->ref_rate = clk_get_rate(drv->ref_clk);
	if (drv->cfg->rate_to_clk) {
		ret = drv->cfg->rate_to_clk(drv->ref_rate, &drv->ref_reg_val);
		if (ret)
			return ret;
	}

	drv->vbus = devm_regulator_get(dev, "vbus");
	if (IS_ERR(drv->vbus)) {
		ret = PTR_ERR(drv->vbus);
		if (ret == -EPROBE_DEFER)
			return ret;
		drv->vbus = NULL;
	}

	for (i = 0; i < drv->cfg->num_phys; i++) {
		char *label = drv->cfg->phys[i].label;
		struct samsung_usb2_phy_instance *p = &drv->instances[i];

		dev_dbg(dev, "Creating phy \"%s\"\n", label);
		p->phy = devm_phy_create(dev, NULL, &samsung_usb2_phy_ops);
		if (IS_ERR(p->phy)) {
			dev_err(drv->dev, "Failed to create usb2_phy \"%s\"\n",
				label);
			return PTR_ERR(p->phy);
		}

		p->cfg = &drv->cfg->phys[i];
		p->drv = drv;
		phy_set_bus_width(p->phy, 8);
		phy_set_drvdata(p->phy, p);
	}

	phy_provider = devm_of_phy_provider_register(dev,
							samsung_usb2_phy_xlate);
	if (IS_ERR(phy_provider)) {
		dev_err(drv->dev, "Failed to register phy provider\n");
		return PTR_ERR(phy_provider);
	}

	return 0;
}

static struct platform_driver samsung_usb2_phy_driver = {
	.probe	= samsung_usb2_phy_probe,
	.driver = {
		.of_match_table	= samsung_usb2_phy_of_match,
		.name		= "samsung-usb2-phy",
	}
};

module_platform_driver(samsung_usb2_phy_driver);
MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC USB PHY driver");
MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:samsung-usb2-phy");
