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

	return 0;

err_instance_clk:
	clk_disable_unprepare(drv->clk);
err_main_clk:
	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);
	}
	clk_disable_unprepare(drv->ref_clk);
	clk_disable_unprepare(drv->clk);
	return ret;
}

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

	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,
					 NULL);
		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");
