// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2018 Marvell
 *
 * Authors:
 *   Igal Liberman <igall@marvell.com>
 *   Miquèl Raynal <miquel.raynal@bootlin.com>
 *
 * Marvell A3700 UTMI PHY driver
 */

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

/* Armada 3700 UTMI PHY registers */
#define USB2_PHY_PLL_CTRL_REG0			0x0
#define   PLL_REF_DIV_OFF			0
#define   PLL_REF_DIV_MASK			GENMASK(6, 0)
#define   PLL_REF_DIV_5				5
#define   PLL_FB_DIV_OFF			16
#define   PLL_FB_DIV_MASK			GENMASK(24, 16)
#define   PLL_FB_DIV_96				96
#define   PLL_SEL_LPFR_OFF			28
#define   PLL_SEL_LPFR_MASK			GENMASK(29, 28)
#define   PLL_READY				BIT(31)
#define USB2_PHY_CAL_CTRL			0x8
#define   PHY_PLLCAL_DONE			BIT(31)
#define   PHY_IMPCAL_DONE			BIT(23)
#define USB2_RX_CHAN_CTRL1			0x18
#define   USB2PHY_SQCAL_DONE			BIT(31)
#define USB2_PHY_OTG_CTRL			0x34
#define   PHY_PU_OTG				BIT(4)
#define USB2_PHY_CHRGR_DETECT			0x38
#define   PHY_CDP_EN				BIT(2)
#define   PHY_DCP_EN				BIT(3)
#define   PHY_PD_EN				BIT(4)
#define   PHY_PU_CHRG_DTC			BIT(5)
#define   PHY_CDP_DM_AUTO			BIT(7)
#define   PHY_ENSWITCH_DP			BIT(12)
#define   PHY_ENSWITCH_DM			BIT(13)

/* Armada 3700 USB miscellaneous registers */
#define USB2_PHY_CTRL(usb32)			(usb32 ? 0x20 : 0x4)
#define   RB_USB2PHY_PU				BIT(0)
#define   USB2_DP_PULLDN_DEV_MODE		BIT(5)
#define   USB2_DM_PULLDN_DEV_MODE		BIT(6)
#define   RB_USB2PHY_SUSPM(usb32)		(usb32 ? BIT(14) : BIT(7))

#define PLL_LOCK_DELAY_US			10000
#define PLL_LOCK_TIMEOUT_US			1000000

/**
 * struct mvebu_a3700_utmi_caps - PHY capabilities
 *
 * @usb32: Flag indicating which PHY is in use (impacts the register map):
 *           - The UTMI PHY wired to the USB3/USB2 controller (otg)
 *           - The UTMI PHY wired to the USB2 controller (host only)
 * @ops: PHY operations
 */
struct mvebu_a3700_utmi_caps {
	int usb32;
	const struct phy_ops *ops;
};

/**
 * struct mvebu_a3700_utmi - PHY driver data
 *
 * @regs: PHY registers
 * @usb_misc: Regmap with USB miscellaneous registers including PHY ones
 * @caps: PHY capabilities
 * @phy: PHY handle
 */
struct mvebu_a3700_utmi {
	void __iomem *regs;
	struct regmap *usb_misc;
	const struct mvebu_a3700_utmi_caps *caps;
	struct phy *phy;
};

static int mvebu_a3700_utmi_phy_power_on(struct phy *phy)
{
	struct mvebu_a3700_utmi *utmi = phy_get_drvdata(phy);
	struct device *dev = &phy->dev;
	int usb32 = utmi->caps->usb32;
	int ret = 0;
	u32 reg;

	/*
	 * Setup PLL. 40MHz clock used to be the default, being 25MHz now.
	 * See "PLL Settings for Typical REFCLK" table.
	 */
	reg = readl(utmi->regs + USB2_PHY_PLL_CTRL_REG0);
	reg &= ~(PLL_REF_DIV_MASK | PLL_FB_DIV_MASK | PLL_SEL_LPFR_MASK);
	reg |= (PLL_REF_DIV_5 << PLL_REF_DIV_OFF) |
	       (PLL_FB_DIV_96 << PLL_FB_DIV_OFF);
	writel(reg, utmi->regs + USB2_PHY_PLL_CTRL_REG0);

	/* Enable PHY pull up and disable USB2 suspend */
	regmap_update_bits(utmi->usb_misc, USB2_PHY_CTRL(usb32),
			   RB_USB2PHY_SUSPM(usb32) | RB_USB2PHY_PU,
			   RB_USB2PHY_SUSPM(usb32) | RB_USB2PHY_PU);

	if (usb32) {
		/* Power up OTG module */
		reg = readl(utmi->regs + USB2_PHY_OTG_CTRL);
		reg |= PHY_PU_OTG;
		writel(reg, utmi->regs + USB2_PHY_OTG_CTRL);

		/* Disable PHY charger detection */
		reg = readl(utmi->regs + USB2_PHY_CHRGR_DETECT);
		reg &= ~(PHY_CDP_EN | PHY_DCP_EN | PHY_PD_EN | PHY_PU_CHRG_DTC |
			 PHY_CDP_DM_AUTO | PHY_ENSWITCH_DP | PHY_ENSWITCH_DM);
		writel(reg, utmi->regs + USB2_PHY_CHRGR_DETECT);

		/* Disable PHY DP/DM pull-down (used for device mode) */
		regmap_update_bits(utmi->usb_misc, USB2_PHY_CTRL(usb32),
				   USB2_DP_PULLDN_DEV_MODE |
				   USB2_DM_PULLDN_DEV_MODE, 0);
	}

	/* Wait for PLL calibration */
	ret = readl_poll_timeout(utmi->regs + USB2_PHY_CAL_CTRL, reg,
				 reg & PHY_PLLCAL_DONE,
				 PLL_LOCK_DELAY_US, PLL_LOCK_TIMEOUT_US);
	if (ret) {
		dev_err(dev, "Failed to end USB2 PLL calibration\n");
		return ret;
	}

	/* Wait for impedance calibration */
	ret = readl_poll_timeout(utmi->regs + USB2_PHY_CAL_CTRL, reg,
				 reg & PHY_IMPCAL_DONE,
				 PLL_LOCK_DELAY_US, PLL_LOCK_TIMEOUT_US);
	if (ret) {
		dev_err(dev, "Failed to end USB2 impedance calibration\n");
		return ret;
	}

	/* Wait for squelch calibration */
	ret = readl_poll_timeout(utmi->regs + USB2_RX_CHAN_CTRL1, reg,
				 reg & USB2PHY_SQCAL_DONE,
				 PLL_LOCK_DELAY_US, PLL_LOCK_TIMEOUT_US);
	if (ret) {
		dev_err(dev, "Failed to end USB2 unknown calibration\n");
		return ret;
	}

	/* Wait for PLL to be locked */
	ret = readl_poll_timeout(utmi->regs + USB2_PHY_PLL_CTRL_REG0, reg,
				 reg & PLL_READY,
				 PLL_LOCK_DELAY_US, PLL_LOCK_TIMEOUT_US);
	if (ret)
		dev_err(dev, "Failed to lock USB2 PLL\n");

	return ret;
}

static int mvebu_a3700_utmi_phy_power_off(struct phy *phy)
{
	struct mvebu_a3700_utmi *utmi = phy_get_drvdata(phy);
	int usb32 = utmi->caps->usb32;
	u32 reg;

	/* Disable PHY pull-up and enable USB2 suspend */
	reg = readl(utmi->regs + USB2_PHY_CTRL(usb32));
	reg &= ~(RB_USB2PHY_PU | RB_USB2PHY_SUSPM(usb32));
	writel(reg, utmi->regs + USB2_PHY_CTRL(usb32));

	/* Power down OTG module */
	if (usb32) {
		reg = readl(utmi->regs + USB2_PHY_OTG_CTRL);
		reg &= ~PHY_PU_OTG;
		writel(reg, utmi->regs + USB2_PHY_OTG_CTRL);
	}

	return 0;
}

static const struct phy_ops mvebu_a3700_utmi_phy_ops = {
	.power_on = mvebu_a3700_utmi_phy_power_on,
	.power_off = mvebu_a3700_utmi_phy_power_off,
	.owner = THIS_MODULE,
};

static const struct mvebu_a3700_utmi_caps mvebu_a3700_utmi_otg_phy_caps = {
	.usb32 = true,
	.ops = &mvebu_a3700_utmi_phy_ops,
};

static const struct mvebu_a3700_utmi_caps mvebu_a3700_utmi_host_phy_caps = {
	.usb32 = false,
	.ops = &mvebu_a3700_utmi_phy_ops,
};

static const struct of_device_id mvebu_a3700_utmi_of_match[] = {
	{
		.compatible = "marvell,a3700-utmi-otg-phy",
		.data = &mvebu_a3700_utmi_otg_phy_caps,
	},
	{
		.compatible = "marvell,a3700-utmi-host-phy",
		.data = &mvebu_a3700_utmi_host_phy_caps,
	},
	{},
};
MODULE_DEVICE_TABLE(of, mvebu_a3700_utmi_of_match);

static int mvebu_a3700_utmi_phy_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct mvebu_a3700_utmi *utmi;
	struct phy_provider *provider;

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

	/* Get UTMI memory region */
	utmi->regs = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(utmi->regs))
		return PTR_ERR(utmi->regs);

	/* Get miscellaneous Host/PHY region */
	utmi->usb_misc = syscon_regmap_lookup_by_phandle(dev->of_node,
							 "marvell,usb-misc-reg");
	if (IS_ERR(utmi->usb_misc)) {
		dev_err(dev,
			"Missing USB misc purpose system controller\n");
		return PTR_ERR(utmi->usb_misc);
	}

	/* Retrieve PHY capabilities */
	utmi->caps = of_device_get_match_data(dev);

	/* Instantiate the PHY */
	utmi->phy = devm_phy_create(dev, NULL, utmi->caps->ops);
	if (IS_ERR(utmi->phy)) {
		dev_err(dev, "Failed to create the UTMI PHY\n");
		return PTR_ERR(utmi->phy);
	}

	phy_set_drvdata(utmi->phy, utmi);

	/* Ensure the PHY is powered off */
	utmi->caps->ops->power_off(utmi->phy);

	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);

	return PTR_ERR_OR_ZERO(provider);
}

static struct platform_driver mvebu_a3700_utmi_driver = {
	.probe	= mvebu_a3700_utmi_phy_probe,
	.driver	= {
		.name		= "mvebu-a3700-utmi-phy",
		.of_match_table	= mvebu_a3700_utmi_of_match,
	 },
};
module_platform_driver(mvebu_a3700_utmi_driver);

MODULE_AUTHOR("Igal Liberman <igall@marvell.com>");
MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
MODULE_DESCRIPTION("Marvell EBU A3700 UTMI PHY driver");
MODULE_LICENSE("GPL v2");
