/*
 * Copyright (c) 2014 Linaro Ltd.
 * Copyright (c) 2014 Hisilicon Limited.
 *
 * 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.
 */

#include <linux/delay.h>
#include <linux/io.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>

#define SATA_PHY0_CTLL		0xa0
#define MPLL_MULTIPLIER_SHIFT	1
#define MPLL_MULTIPLIER_MASK	0xfe
#define MPLL_MULTIPLIER_50M	0x3c
#define MPLL_MULTIPLIER_100M	0x1e
#define PHY_RESET		BIT(0)
#define REF_SSP_EN		BIT(9)
#define SSC_EN			BIT(10)
#define REF_USE_PAD		BIT(23)

#define SATA_PORT_PHYCTL	0x174
#define SPEED_MODE_MASK		0x6f0000
#define HALF_RATE_SHIFT		16
#define PHY_CONFIG_SHIFT	18
#define GEN2_EN_SHIFT		21
#define SPEED_CTRL		BIT(20)

#define SATA_PORT_PHYCTL1	0x148
#define AMPLITUDE_MASK		0x3ffffe
#define AMPLITUDE_GEN3		0x68
#define AMPLITUDE_GEN3_SHIFT	15
#define AMPLITUDE_GEN2		0x56
#define AMPLITUDE_GEN2_SHIFT	8
#define AMPLITUDE_GEN1		0x56
#define AMPLITUDE_GEN1_SHIFT	1

#define SATA_PORT_PHYCTL2	0x14c
#define PREEMPH_MASK		0x3ffff
#define PREEMPH_GEN3		0x20
#define PREEMPH_GEN3_SHIFT	12
#define PREEMPH_GEN2		0x15
#define PREEMPH_GEN2_SHIFT	6
#define PREEMPH_GEN1		0x5
#define PREEMPH_GEN1_SHIFT	0

struct hix5hd2_priv {
	void __iomem	*base;
	struct regmap	*peri_ctrl;
};

enum phy_speed_mode {
	SPEED_MODE_GEN1 = 0,
	SPEED_MODE_GEN2 = 1,
	SPEED_MODE_GEN3 = 2,
};

static int hix5hd2_sata_phy_init(struct phy *phy)
{
	struct hix5hd2_priv *priv = phy_get_drvdata(phy);
	u32 val, data[2];
	int ret;

	if (priv->peri_ctrl) {
		ret = of_property_read_u32_array(phy->dev.of_node,
						 "hisilicon,power-reg",
						 &data[0], 2);
		if (ret) {
			dev_err(&phy->dev, "Fail read hisilicon,power-reg\n");
			return ret;
		}

		regmap_update_bits(priv->peri_ctrl, data[0],
				   BIT(data[1]), BIT(data[1]));
	}

	/* reset phy */
	val = readl_relaxed(priv->base + SATA_PHY0_CTLL);
	val &= ~(MPLL_MULTIPLIER_MASK | REF_USE_PAD);
	val |= MPLL_MULTIPLIER_50M << MPLL_MULTIPLIER_SHIFT |
	       REF_SSP_EN | PHY_RESET;
	writel_relaxed(val, priv->base + SATA_PHY0_CTLL);
	msleep(20);
	val &= ~PHY_RESET;
	writel_relaxed(val, priv->base + SATA_PHY0_CTLL);

	val = readl_relaxed(priv->base + SATA_PORT_PHYCTL1);
	val &= ~AMPLITUDE_MASK;
	val |= AMPLITUDE_GEN3 << AMPLITUDE_GEN3_SHIFT |
	       AMPLITUDE_GEN2 << AMPLITUDE_GEN2_SHIFT |
	       AMPLITUDE_GEN1 << AMPLITUDE_GEN1_SHIFT;
	writel_relaxed(val, priv->base + SATA_PORT_PHYCTL1);

	val = readl_relaxed(priv->base + SATA_PORT_PHYCTL2);
	val &= ~PREEMPH_MASK;
	val |= PREEMPH_GEN3 << PREEMPH_GEN3_SHIFT |
	       PREEMPH_GEN2 << PREEMPH_GEN2_SHIFT |
	       PREEMPH_GEN1 << PREEMPH_GEN1_SHIFT;
	writel_relaxed(val, priv->base + SATA_PORT_PHYCTL2);

	/* ensure PHYCTRL setting takes effect */
	val = readl_relaxed(priv->base + SATA_PORT_PHYCTL);
	val &= ~SPEED_MODE_MASK;
	val |= SPEED_MODE_GEN1 << HALF_RATE_SHIFT |
	       SPEED_MODE_GEN1 << PHY_CONFIG_SHIFT |
	       SPEED_MODE_GEN1 << GEN2_EN_SHIFT | SPEED_CTRL;
	writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);

	msleep(20);
	val &= ~SPEED_MODE_MASK;
	val |= SPEED_MODE_GEN3 << HALF_RATE_SHIFT |
	       SPEED_MODE_GEN3 << PHY_CONFIG_SHIFT |
	       SPEED_MODE_GEN3 << GEN2_EN_SHIFT | SPEED_CTRL;
	writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);

	val &= ~(SPEED_MODE_MASK | SPEED_CTRL);
	val |= SPEED_MODE_GEN2 << HALF_RATE_SHIFT |
	       SPEED_MODE_GEN2 << PHY_CONFIG_SHIFT |
	       SPEED_MODE_GEN2 << GEN2_EN_SHIFT;
	writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);

	return 0;
}

static struct phy_ops hix5hd2_sata_phy_ops = {
	.init		= hix5hd2_sata_phy_init,
	.owner		= THIS_MODULE,
};

static int hix5hd2_sata_phy_probe(struct platform_device *pdev)
{
	struct phy_provider *phy_provider;
	struct device *dev = &pdev->dev;
	struct resource *res;
	struct phy *phy;
	struct hix5hd2_priv *priv;

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

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	priv->base = devm_ioremap(dev, res->start, resource_size(res));
	if (!priv->base)
		return -ENOMEM;

	priv->peri_ctrl = syscon_regmap_lookup_by_phandle(dev->of_node,
					"hisilicon,peripheral-syscon");
	if (IS_ERR(priv->peri_ctrl))
		priv->peri_ctrl = NULL;

	phy = devm_phy_create(dev, NULL, &hix5hd2_sata_phy_ops);
	if (IS_ERR(phy)) {
		dev_err(dev, "failed to create PHY\n");
		return PTR_ERR(phy);
	}

	phy_set_drvdata(phy, priv);
	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
	return PTR_ERR_OR_ZERO(phy_provider);
}

static const struct of_device_id hix5hd2_sata_phy_of_match[] = {
	{.compatible = "hisilicon,hix5hd2-sata-phy",},
	{ },
};
MODULE_DEVICE_TABLE(of, hix5hd2_sata_phy_of_match);

static struct platform_driver hix5hd2_sata_phy_driver = {
	.probe	= hix5hd2_sata_phy_probe,
	.driver = {
		.name	= "hix5hd2-sata-phy",
		.of_match_table	= hix5hd2_sata_phy_of_match,
	}
};
module_platform_driver(hix5hd2_sata_phy_driver);

MODULE_AUTHOR("Jiancheng Xue <xuejiancheng@huawei.com>");
MODULE_DESCRIPTION("HISILICON HIX5HD2 SATA PHY driver");
MODULE_ALIAS("platform:hix5hd2-sata-phy");
MODULE_LICENSE("GPL v2");
