/*
 * Marvell Berlin SATA PHY driver
 *
 * Copyright (C) 2014 Marvell Technology Group Ltd.
 *
 * Antoine Ténart <antoine.tenart@free-electrons.com>
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2. This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */

#include <linux/clk.h>
#include <linux/module.h>
#include <linux/phy/phy.h>
#include <linux/io.h>
#include <linux/platform_device.h>

#define HOST_VSA_ADDR		0x0
#define HOST_VSA_DATA		0x4
#define PORT_SCR_CTL		0x2c
#define PORT_VSR_ADDR		0x78
#define PORT_VSR_DATA		0x7c

#define CONTROL_REGISTER	0x0
#define MBUS_SIZE_CONTROL	0x4

#define POWER_DOWN_PHY0			BIT(6)
#define POWER_DOWN_PHY1			BIT(14)
#define MBUS_WRITE_REQUEST_SIZE_128	(BIT(2) << 16)
#define MBUS_READ_REQUEST_SIZE_128	(BIT(2) << 19)

#define BG2_PHY_BASE		0x080
#define BG2Q_PHY_BASE		0x200

/* register 0x01 */
#define REF_FREF_SEL_25		BIT(0)
#define PHY_MODE_SATA		(0x0 << 5)

/* register 0x02 */
#define USE_MAX_PLL_RATE	BIT(12)

/* register 0x23 */
#define DATA_BIT_WIDTH_10	(0x0 << 10)
#define DATA_BIT_WIDTH_20	(0x1 << 10)
#define DATA_BIT_WIDTH_40	(0x2 << 10)

/* register 0x25 */
#define PHY_GEN_MAX_1_5		(0x0 << 10)
#define PHY_GEN_MAX_3_0		(0x1 << 10)
#define PHY_GEN_MAX_6_0		(0x2 << 10)

struct phy_berlin_desc {
	struct phy	*phy;
	u32		power_bit;
	unsigned	index;
};

struct phy_berlin_priv {
	void __iomem		*base;
	spinlock_t		lock;
	struct clk		*clk;
	struct phy_berlin_desc	**phys;
	unsigned		nphys;
	u32			phy_base;
};

static inline void phy_berlin_sata_reg_setbits(void __iomem *ctrl_reg,
			       u32 phy_base, u32 reg, u32 mask, u32 val)
{
	u32 regval;

	/* select register */
	writel(phy_base + reg, ctrl_reg + PORT_VSR_ADDR);

	/* set bits */
	regval = readl(ctrl_reg + PORT_VSR_DATA);
	regval &= ~mask;
	regval |= val;
	writel(regval, ctrl_reg + PORT_VSR_DATA);
}

static int phy_berlin_sata_power_on(struct phy *phy)
{
	struct phy_berlin_desc *desc = phy_get_drvdata(phy);
	struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
	void __iomem *ctrl_reg = priv->base + 0x60 + (desc->index * 0x80);
	int ret = 0;
	u32 regval;

	clk_prepare_enable(priv->clk);

	spin_lock(&priv->lock);

	/* Power on PHY */
	writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
	regval = readl(priv->base + HOST_VSA_DATA);
	regval &= ~desc->power_bit;
	writel(regval, priv->base + HOST_VSA_DATA);

	/* Configure MBus */
	writel(MBUS_SIZE_CONTROL, priv->base + HOST_VSA_ADDR);
	regval = readl(priv->base + HOST_VSA_DATA);
	regval |= MBUS_WRITE_REQUEST_SIZE_128 | MBUS_READ_REQUEST_SIZE_128;
	writel(regval, priv->base + HOST_VSA_DATA);

	/* set PHY mode and ref freq to 25 MHz */
	phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x01,
				    0x00ff, REF_FREF_SEL_25 | PHY_MODE_SATA);

	/* set PHY up to 6 Gbps */
	phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x25,
				    0x0c00, PHY_GEN_MAX_6_0);

	/* set 40 bits width */
	phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x23,
				    0x0c00, DATA_BIT_WIDTH_40);

	/* use max pll rate */
	phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x02,
				    0x0000, USE_MAX_PLL_RATE);

	/* set Gen3 controller speed */
	regval = readl(ctrl_reg + PORT_SCR_CTL);
	regval &= ~GENMASK(7, 4);
	regval |= 0x30;
	writel(regval, ctrl_reg + PORT_SCR_CTL);

	spin_unlock(&priv->lock);

	clk_disable_unprepare(priv->clk);

	return ret;
}

static int phy_berlin_sata_power_off(struct phy *phy)
{
	struct phy_berlin_desc *desc = phy_get_drvdata(phy);
	struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
	u32 regval;

	clk_prepare_enable(priv->clk);

	spin_lock(&priv->lock);

	/* Power down PHY */
	writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
	regval = readl(priv->base + HOST_VSA_DATA);
	regval |= desc->power_bit;
	writel(regval, priv->base + HOST_VSA_DATA);

	spin_unlock(&priv->lock);

	clk_disable_unprepare(priv->clk);

	return 0;
}

static struct phy *phy_berlin_sata_phy_xlate(struct device *dev,
					     struct of_phandle_args *args)
{
	struct phy_berlin_priv *priv = dev_get_drvdata(dev);
	int i;

	if (WARN_ON(args->args[0] >= priv->nphys))
		return ERR_PTR(-ENODEV);

	for (i = 0; i < priv->nphys; i++) {
		if (priv->phys[i]->index == args->args[0])
			break;
	}

	if (i == priv->nphys)
		return ERR_PTR(-ENODEV);

	return priv->phys[i]->phy;
}

static const struct phy_ops phy_berlin_sata_ops = {
	.power_on	= phy_berlin_sata_power_on,
	.power_off	= phy_berlin_sata_power_off,
	.owner		= THIS_MODULE,
};

static u32 phy_berlin_power_down_bits[] = {
	POWER_DOWN_PHY0,
	POWER_DOWN_PHY1,
};

static int phy_berlin_sata_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct device_node *child;
	struct phy *phy;
	struct phy_provider *phy_provider;
	struct phy_berlin_priv *priv;
	struct resource *res;
	int ret, i = 0;
	u32 phy_id;

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

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
		return -EINVAL;

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

	priv->clk = devm_clk_get(dev, NULL);
	if (IS_ERR(priv->clk))
		return PTR_ERR(priv->clk);

	priv->nphys = of_get_child_count(dev->of_node);
	if (priv->nphys == 0)
		return -ENODEV;

	priv->phys = devm_kcalloc(dev, priv->nphys, sizeof(*priv->phys),
				  GFP_KERNEL);
	if (!priv->phys)
		return -ENOMEM;

	if (of_device_is_compatible(dev->of_node, "marvell,berlin2-sata-phy"))
		priv->phy_base = BG2_PHY_BASE;
	else
		priv->phy_base = BG2Q_PHY_BASE;

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

	for_each_available_child_of_node(dev->of_node, child) {
		struct phy_berlin_desc *phy_desc;

		if (of_property_read_u32(child, "reg", &phy_id)) {
			dev_err(dev, "missing reg property in node %s\n",
				child->name);
			ret = -EINVAL;
			goto put_child;
		}

		if (phy_id >= ARRAY_SIZE(phy_berlin_power_down_bits)) {
			dev_err(dev, "invalid reg in node %s\n", child->name);
			ret = -EINVAL;
			goto put_child;
		}

		phy_desc = devm_kzalloc(dev, sizeof(*phy_desc), GFP_KERNEL);
		if (!phy_desc) {
			ret = -ENOMEM;
			goto put_child;
		}

		phy = devm_phy_create(dev, NULL, &phy_berlin_sata_ops);
		if (IS_ERR(phy)) {
			dev_err(dev, "failed to create PHY %d\n", phy_id);
			ret = PTR_ERR(phy);
			goto put_child;
		}

		phy_desc->phy = phy;
		phy_desc->power_bit = phy_berlin_power_down_bits[phy_id];
		phy_desc->index = phy_id;
		phy_set_drvdata(phy, phy_desc);

		priv->phys[i++] = phy_desc;

		/* Make sure the PHY is off */
		phy_berlin_sata_power_off(phy);
	}

	phy_provider =
		devm_of_phy_provider_register(dev, phy_berlin_sata_phy_xlate);
	return PTR_ERR_OR_ZERO(phy_provider);
put_child:
	of_node_put(child);
	return ret;
}

static const struct of_device_id phy_berlin_sata_of_match[] = {
	{ .compatible = "marvell,berlin2-sata-phy" },
	{ .compatible = "marvell,berlin2q-sata-phy" },
	{ },
};
MODULE_DEVICE_TABLE(of, phy_berlin_sata_of_match);

static struct platform_driver phy_berlin_sata_driver = {
	.probe	= phy_berlin_sata_probe,
	.driver	= {
		.name		= "phy-berlin-sata",
		.of_match_table	= phy_berlin_sata_of_match,
	},
};
module_platform_driver(phy_berlin_sata_driver);

MODULE_DESCRIPTION("Marvell Berlin SATA PHY driver");
MODULE_AUTHOR("Antoine Ténart <antoine.tenart@free-electrons.com>");
MODULE_LICENSE("GPL v2");
