/*
 * COMBPHY driver for HiSilicon STB SoCs
 *
 * Copyright (C) 2016-2017 HiSilicon Co., Ltd. http://www.hisilicon.com
 *
 * Authors: Jianguo Sun <sunjianguo1@huawei.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/delay.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/phy/phy.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <dt-bindings/phy/phy.h>

#define COMBPHY_MODE_PCIE		0
#define COMBPHY_MODE_USB3		1
#define COMBPHY_MODE_SATA		2

#define COMBPHY_CFG_REG			0x0
#define COMBPHY_BYPASS_CODEC		BIT(31)
#define COMBPHY_TEST_WRITE		BIT(24)
#define COMBPHY_TEST_DATA_SHIFT		20
#define COMBPHY_TEST_DATA_MASK		GENMASK(23, 20)
#define COMBPHY_TEST_ADDR_SHIFT		12
#define COMBPHY_TEST_ADDR_MASK		GENMASK(16, 12)
#define COMBPHY_CLKREF_OUT_OEN		BIT(0)

struct histb_combphy_mode {
	int fixed;
	int select;
	u32 reg;
	u32 shift;
	u32 mask;
};

struct histb_combphy_priv {
	void __iomem *mmio;
	struct regmap *syscon;
	struct reset_control *por_rst;
	struct clk *ref_clk;
	struct phy *phy;
	struct histb_combphy_mode mode;
};

static void nano_register_write(struct histb_combphy_priv *priv,
				u32 addr, u32 data)
{
	void __iomem *reg = priv->mmio + COMBPHY_CFG_REG;
	u32 val;

	/* Set up address and data for the write */
	val = readl(reg);
	val &= ~COMBPHY_TEST_ADDR_MASK;
	val |= addr << COMBPHY_TEST_ADDR_SHIFT;
	val &= ~COMBPHY_TEST_DATA_MASK;
	val |= data << COMBPHY_TEST_DATA_SHIFT;
	writel(val, reg);

	/* Flip strobe control to trigger the write */
	val &= ~COMBPHY_TEST_WRITE;
	writel(val, reg);
	val |= COMBPHY_TEST_WRITE;
	writel(val, reg);
}

static int is_mode_fixed(struct histb_combphy_mode *mode)
{
	return (mode->fixed != PHY_NONE) ? true : false;
}

static int histb_combphy_set_mode(struct histb_combphy_priv *priv)
{
	struct histb_combphy_mode *mode = &priv->mode;
	struct regmap *syscon = priv->syscon;
	u32 hw_sel;

	if (is_mode_fixed(mode))
		return 0;

	switch (mode->select) {
	case PHY_TYPE_SATA:
		hw_sel = COMBPHY_MODE_SATA;
		break;
	case PHY_TYPE_PCIE:
		hw_sel = COMBPHY_MODE_PCIE;
		break;
	case PHY_TYPE_USB3:
		hw_sel = COMBPHY_MODE_USB3;
		break;
	default:
		return -EINVAL;
	}

	return regmap_update_bits(syscon, mode->reg, mode->mask,
				  hw_sel << mode->shift);
}

static int histb_combphy_init(struct phy *phy)
{
	struct histb_combphy_priv *priv = phy_get_drvdata(phy);
	u32 val;
	int ret;

	ret = histb_combphy_set_mode(priv);
	if (ret)
		return ret;

	/* Clear bypass bit to enable encoding/decoding */
	val = readl(priv->mmio + COMBPHY_CFG_REG);
	val &= ~COMBPHY_BYPASS_CODEC;
	writel(val, priv->mmio + COMBPHY_CFG_REG);

	ret = clk_prepare_enable(priv->ref_clk);
	if (ret)
		return ret;

	reset_control_deassert(priv->por_rst);

	/* Enable EP clock */
	val = readl(priv->mmio + COMBPHY_CFG_REG);
	val |= COMBPHY_CLKREF_OUT_OEN;
	writel(val, priv->mmio + COMBPHY_CFG_REG);

	/* Need to wait for EP clock stable */
	mdelay(5);

	/* Configure nano phy registers as suggested by vendor */
	nano_register_write(priv, 0x1, 0x8);
	nano_register_write(priv, 0xc, 0x9);
	nano_register_write(priv, 0x1a, 0x4);

	return 0;
}

static int histb_combphy_exit(struct phy *phy)
{
	struct histb_combphy_priv *priv = phy_get_drvdata(phy);
	u32 val;

	/* Disable EP clock */
	val = readl(priv->mmio + COMBPHY_CFG_REG);
	val &= ~COMBPHY_CLKREF_OUT_OEN;
	writel(val, priv->mmio + COMBPHY_CFG_REG);

	reset_control_assert(priv->por_rst);
	clk_disable_unprepare(priv->ref_clk);

	return 0;
}

static const struct phy_ops histb_combphy_ops = {
	.init = histb_combphy_init,
	.exit = histb_combphy_exit,
	.owner = THIS_MODULE,
};

static struct phy *histb_combphy_xlate(struct device *dev,
				       struct of_phandle_args *args)
{
	struct histb_combphy_priv *priv = dev_get_drvdata(dev);
	struct histb_combphy_mode *mode = &priv->mode;

	if (args->args_count < 1) {
		dev_err(dev, "invalid number of arguments\n");
		return ERR_PTR(-EINVAL);
	}

	mode->select = args->args[0];

	if (mode->select < PHY_TYPE_SATA || mode->select > PHY_TYPE_USB3) {
		dev_err(dev, "invalid phy mode select argument\n");
		return ERR_PTR(-EINVAL);
	}

	if (is_mode_fixed(mode) && mode->select != mode->fixed) {
		dev_err(dev, "mode select %d mismatch fixed phy mode %d\n",
			mode->select, mode->fixed);
		return ERR_PTR(-EINVAL);
	}

	return priv->phy;
}

static int histb_combphy_probe(struct platform_device *pdev)
{
	struct phy_provider *phy_provider;
	struct device *dev = &pdev->dev;
	struct histb_combphy_priv *priv;
	struct device_node *np = dev->of_node;
	struct histb_combphy_mode *mode;
	struct resource *res;
	u32 vals[3];
	int ret;

	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	priv->mmio = devm_ioremap_resource(dev, res);
	if (IS_ERR(priv->mmio)) {
		ret = PTR_ERR(priv->mmio);
		return ret;
	}

	priv->syscon = syscon_node_to_regmap(np->parent);
	if (IS_ERR(priv->syscon)) {
		dev_err(dev, "failed to find peri_ctrl syscon regmap\n");
		return PTR_ERR(priv->syscon);
	}

	mode = &priv->mode;
	mode->fixed = PHY_NONE;

	ret = of_property_read_u32(np, "hisilicon,fixed-mode", &mode->fixed);
	if (ret == 0)
		dev_dbg(dev, "found fixed phy mode %d\n", mode->fixed);

	ret = of_property_read_u32_array(np, "hisilicon,mode-select-bits",
					 vals, ARRAY_SIZE(vals));
	if (ret == 0) {
		if (is_mode_fixed(mode)) {
			dev_err(dev, "found select bits for fixed mode phy\n");
			return -EINVAL;
		}

		mode->reg = vals[0];
		mode->shift = vals[1];
		mode->mask = vals[2];
		dev_dbg(dev, "found mode select bits\n");
	} else {
		if (!is_mode_fixed(mode)) {
			dev_err(dev, "no valid select bits found for non-fixed phy\n");
			return -ENODEV;
		}
	}

	priv->ref_clk = devm_clk_get(dev, NULL);
	if (IS_ERR(priv->ref_clk)) {
		dev_err(dev, "failed to find ref clock\n");
		return PTR_ERR(priv->ref_clk);
	}

	priv->por_rst = devm_reset_control_get(dev, NULL);
	if (IS_ERR(priv->por_rst)) {
		dev_err(dev, "failed to get poweron reset\n");
		return PTR_ERR(priv->por_rst);
	}

	priv->phy = devm_phy_create(dev, NULL, &histb_combphy_ops);
	if (IS_ERR(priv->phy)) {
		dev_err(dev, "failed to create combphy\n");
		return PTR_ERR(priv->phy);
	}

	dev_set_drvdata(dev, priv);
	phy_set_drvdata(priv->phy, priv);

	phy_provider = devm_of_phy_provider_register(dev, histb_combphy_xlate);
	return PTR_ERR_OR_ZERO(phy_provider);
}

static const struct of_device_id histb_combphy_of_match[] = {
	{ .compatible = "hisilicon,hi3798cv200-combphy" },
	{ },
};
MODULE_DEVICE_TABLE(of, histb_combphy_of_match);

static struct platform_driver histb_combphy_driver = {
	.probe	= histb_combphy_probe,
	.driver = {
		.name = "combphy",
		.of_match_table = histb_combphy_of_match,
	},
};
module_platform_driver(histb_combphy_driver);

MODULE_DESCRIPTION("HiSilicon STB COMBPHY driver");
MODULE_LICENSE("GPL v2");
