// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/
 */

#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/phy/phy.h>
#include <linux/phy/phy-mipi-dphy.h>
#include <linux/platform_device.h>

#define DPHY_PMA_CMN(reg)		(reg)
#define DPHY_PCS(reg)			(0xb00 + (reg))
#define DPHY_ISO(reg)			(0xc00 + (reg))

#define DPHY_CMN_SSM			DPHY_PMA_CMN(0x20)
#define DPHY_CMN_RX_MODE_EN		BIT(10)
#define DPHY_CMN_RX_BANDGAP_TIMER_MASK	GENMASK(8, 1)
#define DPHY_CMN_SSM_EN			BIT(0)

#define DPHY_CMN_RX_BANDGAP_TIMER	0x14

#define DPHY_BAND_CFG			DPHY_PCS(0x0)
#define DPHY_BAND_CFG_RIGHT_BAND	GENMASK(9, 5)
#define DPHY_BAND_CFG_LEFT_BAND		GENMASK(4, 0)

#define DPHY_POWER_ISLAND_EN_DATA	DPHY_PCS(0x8)
#define DPHY_POWER_ISLAND_EN_DATA_VAL	0xaaaaaaaa

#define DPHY_POWER_ISLAND_EN_CLK	DPHY_PCS(0xc)
#define DPHY_POWER_ISLAND_EN_CLK_VAL	0xaa

#define DPHY_ISO_CL_CTRL_L		DPHY_ISO(0x10)
#define DPHY_ISO_DL_CTRL_L0		DPHY_ISO(0x14)
#define DPHY_ISO_DL_CTRL_L1		DPHY_ISO(0x20)
#define DPHY_ISO_DL_CTRL_L2		DPHY_ISO(0x30)
#define DPHY_ISO_DL_CTRL_L3		DPHY_ISO(0x3c)

#define DPHY_ISO_LANE_READY_BIT		0
#define DPHY_ISO_LANE_READY_TIMEOUT_MS	100UL

#define DPHY_LANES_MIN			1
#define DPHY_LANES_MAX			4

struct cdns_dphy_rx {
	void __iomem *regs;
	struct device *dev;
	struct phy *phy;
};

struct cdns_dphy_rx_band {
	/* Rates are in Mbps. */
	unsigned int min_rate;
	unsigned int max_rate;
};

/* Order of bands is important since the index is the band number. */
static const struct cdns_dphy_rx_band bands[] = {
	{ 80, 100 }, { 100, 120 }, { 120, 160 }, { 160, 200 }, { 200, 240 },
	{ 240, 280 }, { 280, 320 }, { 320, 360 }, { 360, 400 }, { 400, 480 },
	{ 480, 560 }, { 560, 640 }, { 640, 720 }, { 720, 800 }, { 800, 880 },
	{ 880, 1040 }, { 1040, 1200 }, { 1200, 1350 }, { 1350, 1500 },
	{ 1500, 1750 }, { 1750, 2000 }, { 2000, 2250 }, { 2250, 2500 }
};

static int cdns_dphy_rx_power_on(struct phy *phy)
{
	struct cdns_dphy_rx *dphy = phy_get_drvdata(phy);

	/* Start RX state machine. */
	writel(DPHY_CMN_SSM_EN | DPHY_CMN_RX_MODE_EN |
	       FIELD_PREP(DPHY_CMN_RX_BANDGAP_TIMER_MASK,
			  DPHY_CMN_RX_BANDGAP_TIMER),
	       dphy->regs + DPHY_CMN_SSM);

	return 0;
}

static int cdns_dphy_rx_power_off(struct phy *phy)
{
	struct cdns_dphy_rx *dphy = phy_get_drvdata(phy);

	writel(0, dphy->regs + DPHY_CMN_SSM);

	return 0;
}

static int cdns_dphy_rx_get_band_ctrl(unsigned long hs_clk_rate)
{
	unsigned int rate, i;

	rate = hs_clk_rate / 1000000UL;
	/* Since CSI-2 clock is DDR, the bit rate is twice the clock rate. */
	rate *= 2;

	if (rate < bands[0].min_rate)
		return -EOPNOTSUPP;

	for (i = 0; i < ARRAY_SIZE(bands); i++)
		if (rate < bands[i].max_rate)
			return i;

	return -EOPNOTSUPP;
}

static inline int cdns_dphy_rx_wait_for_bit(void __iomem *addr,
					    unsigned int bit)
{
	u32 val;

	return readl_relaxed_poll_timeout(addr, val, val & BIT(bit), 10,
					  DPHY_ISO_LANE_READY_TIMEOUT_MS * 1000);
}

static int cdns_dphy_rx_wait_lane_ready(struct cdns_dphy_rx *dphy,
					unsigned int lanes)
{
	static const u32 data_lane_ctrl[] = {DPHY_ISO_DL_CTRL_L0,
					     DPHY_ISO_DL_CTRL_L1,
					     DPHY_ISO_DL_CTRL_L2,
					     DPHY_ISO_DL_CTRL_L3};
	void __iomem *reg = dphy->regs;
	unsigned int i;
	int ret;

	/* Clock lane */
	ret = cdns_dphy_rx_wait_for_bit(reg + DPHY_ISO_CL_CTRL_L,
					DPHY_ISO_LANE_READY_BIT);
	if (ret)
		return ret;

	for (i = 0; i < lanes; i++) {
		ret = cdns_dphy_rx_wait_for_bit(reg + data_lane_ctrl[i],
						DPHY_ISO_LANE_READY_BIT);
		if (ret)
			return ret;
	}

	return 0;
}

static int cdns_dphy_rx_configure(struct phy *phy,
				  union phy_configure_opts *opts)
{
	struct cdns_dphy_rx *dphy = phy_get_drvdata(phy);
	unsigned int reg, lanes = opts->mipi_dphy.lanes;
	int band_ctrl, ret;

	/* Data lanes. Minimum one lane is mandatory. */
	if (lanes < DPHY_LANES_MIN || lanes > DPHY_LANES_MAX)
		return -EINVAL;

	band_ctrl = cdns_dphy_rx_get_band_ctrl(opts->mipi_dphy.hs_clk_rate);
	if (band_ctrl < 0)
		return band_ctrl;

	reg = FIELD_PREP(DPHY_BAND_CFG_LEFT_BAND, band_ctrl) |
	      FIELD_PREP(DPHY_BAND_CFG_RIGHT_BAND, band_ctrl);
	writel(reg, dphy->regs + DPHY_BAND_CFG);

	/*
	 * Set the required power island phase 2 time. This is mandated by DPHY
	 * specs.
	 */
	reg = DPHY_POWER_ISLAND_EN_DATA_VAL;
	writel(reg, dphy->regs + DPHY_POWER_ISLAND_EN_DATA);
	reg = DPHY_POWER_ISLAND_EN_CLK_VAL;
	writel(reg, dphy->regs + DPHY_POWER_ISLAND_EN_CLK);

	ret = cdns_dphy_rx_wait_lane_ready(dphy, lanes);
	if (ret) {
		dev_err(dphy->dev, "DPHY wait for lane ready timeout\n");
		return ret;
	}

	return 0;
}

static int cdns_dphy_rx_validate(struct phy *phy, enum phy_mode mode,
				 int submode, union phy_configure_opts *opts)
{
	int ret;

	if (mode != PHY_MODE_MIPI_DPHY)
		return -EINVAL;

	ret = cdns_dphy_rx_get_band_ctrl(opts->mipi_dphy.hs_clk_rate);
	if (ret < 0)
		return ret;

	return phy_mipi_dphy_config_validate(&opts->mipi_dphy);
}

static const struct phy_ops cdns_dphy_rx_ops = {
	.power_on = cdns_dphy_rx_power_on,
	.power_off = cdns_dphy_rx_power_off,
	.configure = cdns_dphy_rx_configure,
	.validate = cdns_dphy_rx_validate,
};

static int cdns_dphy_rx_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct phy_provider *provider;
	struct cdns_dphy_rx *dphy;

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

	dev_set_drvdata(dev, dphy);
	dphy->dev = dev;

	dphy->regs = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(dphy->regs))
		return PTR_ERR(dphy->regs);

	dphy->phy = devm_phy_create(dev, NULL, &cdns_dphy_rx_ops);
	if (IS_ERR(dphy->phy)) {
		dev_err(dev, "Failed to create PHY: %ld\n", PTR_ERR(dphy->phy));
		return PTR_ERR(dphy->phy);
	}

	phy_set_drvdata(dphy->phy, dphy);
	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
	if (IS_ERR(provider)) {
		dev_err(dev, "Failed to register PHY provider: %ld\n",
			PTR_ERR(provider));
		return PTR_ERR(provider);
	}

	return 0;
}

static const struct of_device_id cdns_dphy_rx_of_match[] = {
	{ .compatible = "cdns,dphy-rx" },
	{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, cdns_dphy_rx_of_match);

static struct platform_driver cdns_dphy_rx_platform_driver = {
	.probe		= cdns_dphy_rx_probe,
	.driver		= {
		.name		= "cdns-mipi-dphy-rx",
		.of_match_table	= cdns_dphy_rx_of_match,
	},
};
module_platform_driver(cdns_dphy_rx_platform_driver);

MODULE_AUTHOR("Pratyush Yadav <p.yadav@ti.com>");
MODULE_DESCRIPTION("Cadence D-PHY Rx Driver");
MODULE_LICENSE("GPL");
