/*
 * SPDX-License-Identifier: GPL-2.0
 * Copyright (c) 2018, The Linux Foundation
 */

#include <linux/iopoll.h>

#include "dsi_phy.h"
#include "dsi.xml.h"

static int dsi_phy_hw_v3_0_is_pll_on(struct msm_dsi_phy *phy)
{
	void __iomem *base = phy->base;
	u32 data = 0;

	data = dsi_phy_read(base + REG_DSI_10nm_PHY_CMN_PLL_CNTRL);
	mb(); /* make sure read happened */

	return (data & BIT(0));
}

static void dsi_phy_hw_v3_0_config_lpcdrx(struct msm_dsi_phy *phy, bool enable)
{
	void __iomem *lane_base = phy->lane_base;
	int phy_lane_0 = 0;	/* TODO: Support all lane swap configs */

	/*
	 * LPRX and CDRX need to enabled only for physical data lane
	 * corresponding to the logical data lane 0
	 */
	if (enable)
		dsi_phy_write(lane_base +
			      REG_DSI_10nm_PHY_LN_LPRX_CTRL(phy_lane_0), 0x3);
	else
		dsi_phy_write(lane_base +
			      REG_DSI_10nm_PHY_LN_LPRX_CTRL(phy_lane_0), 0);
}

static void dsi_phy_hw_v3_0_lane_settings(struct msm_dsi_phy *phy)
{
	int i;
	u8 tx_dctrl[] = { 0x00, 0x00, 0x00, 0x04, 0x01 };
	void __iomem *lane_base = phy->lane_base;

	/* Strength ctrl settings */
	for (i = 0; i < 5; i++) {
		dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_LPTX_STR_CTRL(i),
			      0x55);
		/*
		 * Disable LPRX and CDRX for all lanes. And later on, it will
		 * be only enabled for the physical data lane corresponding
		 * to the logical data lane 0
		 */
		dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_LPRX_CTRL(i), 0);
		dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_PIN_SWAP(i), 0x0);
		dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_HSTX_STR_CTRL(i),
			      0x88);
	}

	dsi_phy_hw_v3_0_config_lpcdrx(phy, true);

	/* other settings */
	for (i = 0; i < 5; i++) {
		dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_CFG0(i), 0x0);
		dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_CFG1(i), 0x0);
		dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_CFG2(i), 0x0);
		dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_CFG3(i),
			      i == 4 ? 0x80 : 0x0);
		dsi_phy_write(lane_base +
			      REG_DSI_10nm_PHY_LN_OFFSET_TOP_CTRL(i), 0x0);
		dsi_phy_write(lane_base +
			      REG_DSI_10nm_PHY_LN_OFFSET_BOT_CTRL(i), 0x0);
		dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_TX_DCTRL(i),
			      tx_dctrl[i]);
	}

	/* Toggle BIT 0 to release freeze I/0 */
	dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_TX_DCTRL(3), 0x05);
	dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_TX_DCTRL(3), 0x04);
}

static int dsi_10nm_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
			       struct msm_dsi_phy_clk_request *clk_req)
{
	int ret;
	u32 status;
	u32 const delay_us = 5;
	u32 const timeout_us = 1000;
	struct msm_dsi_dphy_timing *timing = &phy->timing;
	void __iomem *base = phy->base;
	u32 data;

	DBG("");

	if (msm_dsi_dphy_timing_calc_v3(timing, clk_req)) {
		dev_err(&phy->pdev->dev,
			"%s: D-PHY timing calculation failed\n", __func__);
		return -EINVAL;
	}

	if (dsi_phy_hw_v3_0_is_pll_on(phy))
		pr_warn("PLL turned on before configuring PHY\n");

	/* wait for REFGEN READY */
	ret = readl_poll_timeout_atomic(base + REG_DSI_10nm_PHY_CMN_PHY_STATUS,
					status, (status & BIT(0)),
					delay_us, timeout_us);
	if (ret) {
		pr_err("Ref gen not ready. Aborting\n");
		return -EINVAL;
	}

	/* de-assert digital and pll power down */
	data = BIT(6) | BIT(5);
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_CTRL_0, data);

	/* Assert PLL core reset */
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_PLL_CNTRL, 0x00);

	/* turn off resync FIFO */
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_RBUF_CTRL, 0x00);

	/* Select MS1 byte-clk */
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_GLBL_CTRL, 0x10);

	/* Enable LDO */
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_VREG_CTRL, 0x59);

	/* Configure PHY lane swap (TODO: we need to calculate this) */
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_LANE_CFG0, 0x21);
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_LANE_CFG1, 0x84);

	/* DSI PHY timings */
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_0,
		      timing->hs_halfbyte_en);
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_1,
		      timing->clk_zero);
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_2,
		      timing->clk_prepare);
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_3,
		      timing->clk_trail);
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_4,
		      timing->hs_exit);
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_5,
		      timing->hs_zero);
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_6,
		      timing->hs_prepare);
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_7,
		      timing->hs_trail);
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_8,
		      timing->hs_rqst);
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_9,
		      timing->ta_go | (timing->ta_sure << 3));
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_10,
		      timing->ta_get);
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_TIMING_CTRL_11,
		      0x00);

	/* Remove power down from all blocks */
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_CTRL_0, 0x7f);

	/* power up lanes */
	data = dsi_phy_read(base + REG_DSI_10nm_PHY_CMN_CTRL_0);

	/* TODO: only power up lanes that are used */
	data |= 0x1F;
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_CTRL_0, data);
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_LANE_CTRL0, 0x1F);

	/* Select full-rate mode */
	dsi_phy_write(base + REG_DSI_10nm_PHY_CMN_CTRL_2, 0x40);

	ret = msm_dsi_pll_set_usecase(phy->pll, phy->usecase);
	if (ret) {
		dev_err(&phy->pdev->dev, "%s: set pll usecase failed, %d\n",
			__func__, ret);
		return ret;
	}

	/* DSI lane settings */
	dsi_phy_hw_v3_0_lane_settings(phy);

	DBG("DSI%d PHY enabled", phy->id);

	return 0;
}

static void dsi_10nm_phy_disable(struct msm_dsi_phy *phy)
{
}

static int dsi_10nm_phy_init(struct msm_dsi_phy *phy)
{
	struct platform_device *pdev = phy->pdev;

	phy->lane_base = msm_ioremap(pdev, "dsi_phy_lane",
				     "DSI_PHY_LANE");
	if (IS_ERR(phy->lane_base)) {
		dev_err(&pdev->dev, "%s: failed to map phy lane base\n",
			__func__);
		return -ENOMEM;
	}

	return 0;
}

const struct msm_dsi_phy_cfg dsi_phy_10nm_cfgs = {
	.type = MSM_DSI_PHY_10NM,
	.src_pll_truthtable = { {false, false}, {true, false} },
	.reg_cfg = {
		.num = 1,
		.regs = {
			{"vdds", 36000, 32},
		},
	},
	.ops = {
		.enable = dsi_10nm_phy_enable,
		.disable = dsi_10nm_phy_disable,
		.init = dsi_10nm_phy_init,
	},
	.io_start = { 0xae94400, 0xae96400 },
	.num_dsi_phy = 2,
};
