/*
 * Copyright (C) 2016 Cadence Design Systems - https://www.cadence.com/
 * Copyright 2018 NXP
 *
 * SPDX-License-Identifier:     GPL-2.0
 */
#include <common.h>
#include <malloc.h>
#include <asm/dma-mapping.h>
#include <asm/io.h>
#include <linux/bug.h>
#include <linux/list.h>
#include <linux/compat.h>
#include <cdns3-uboot.h>

#include "linux-compat.h"
#include "cdns3-nxp-reg-def.h"
#include "core.h"
#include "gadget-export.h"

static LIST_HEAD(cdns3_list);

/* Need SoC level to implement the clock */
__weak int cdns3_enable_clks(int index)
{
	return 0;
}

__weak int cdns3_disable_clks(int index)
{
	return 0;
}

static void cdns3_usb_phy_init(void __iomem *regs)
{
	u32 value;

	pr_debug("begin of %s\n", __func__);

	writel(0x0830, regs + PHY_PMA_CMN_CTRL1);
	writel(0x10, regs + TB_ADDR_CMN_DIAG_HSCLK_SEL);
	writel(0x00F0, regs + TB_ADDR_CMN_PLL0_VCOCAL_INIT_TMR);
	writel(0x0018, regs + TB_ADDR_CMN_PLL0_VCOCAL_ITER_TMR);
	writel(0x00D0, regs + TB_ADDR_CMN_PLL0_INTDIV);
	writel(0x4aaa, regs + TB_ADDR_CMN_PLL0_FRACDIV);
	writel(0x0034, regs + TB_ADDR_CMN_PLL0_HIGH_THR);
	writel(0x1ee, regs + TB_ADDR_CMN_PLL0_SS_CTRL1);
	writel(0x7F03, regs + TB_ADDR_CMN_PLL0_SS_CTRL2);
	writel(0x0020, regs + TB_ADDR_CMN_PLL0_DSM_DIAG);
	writel(0x0000, regs + TB_ADDR_CMN_DIAG_PLL0_OVRD);
	writel(0x0000, regs + TB_ADDR_CMN_DIAG_PLL0_FBH_OVRD);
	writel(0x0000, regs + TB_ADDR_CMN_DIAG_PLL0_FBL_OVRD);
	writel(0x0007, regs + TB_ADDR_CMN_DIAG_PLL0_V2I_TUNE);
	writel(0x0027, regs + TB_ADDR_CMN_DIAG_PLL0_CP_TUNE);
	writel(0x0008, regs + TB_ADDR_CMN_DIAG_PLL0_LF_PROG);
	writel(0x0022, regs + TB_ADDR_CMN_DIAG_PLL0_TEST_MODE);
	writel(0x000a, regs + TB_ADDR_CMN_PSM_CLK_CTRL);
	writel(0x139, regs + TB_ADDR_XCVR_DIAG_RX_LANE_CAL_RST_TMR);
	writel(0xbefc, regs + TB_ADDR_XCVR_PSM_RCTRL);

	writel(0x7799, regs + TB_ADDR_TX_PSC_A0);
	writel(0x7798, regs + TB_ADDR_TX_PSC_A1);
	writel(0x509b, regs + TB_ADDR_TX_PSC_A2);
	writel(0x3, regs + TB_ADDR_TX_DIAG_ECTRL_OVRD);
	writel(0x509b, regs + TB_ADDR_TX_PSC_A3);
	writel(0x2090, regs + TB_ADDR_TX_PSC_CAL);
	writel(0x2090, regs + TB_ADDR_TX_PSC_RDY);

	writel(0xA6FD, regs + TB_ADDR_RX_PSC_A0);
	writel(0xA6FD, regs + TB_ADDR_RX_PSC_A1);
	writel(0xA410, regs + TB_ADDR_RX_PSC_A2);
	writel(0x2410, regs + TB_ADDR_RX_PSC_A3);

	writel(0x23FF, regs + TB_ADDR_RX_PSC_CAL);
	writel(0x2010, regs + TB_ADDR_RX_PSC_RDY);

	writel(0x0020, regs + TB_ADDR_TX_TXCC_MGNLS_MULT_000);
	writel(0x00ff, regs + TB_ADDR_TX_DIAG_BGREF_PREDRV_DELAY);
	writel(0x0002, regs + TB_ADDR_RX_SLC_CU_ITER_TMR);
	writel(0x0013, regs + TB_ADDR_RX_SIGDET_HL_FILT_TMR);
	writel(0x0000, regs + TB_ADDR_RX_SAMP_DAC_CTRL);
	writel(0x1004, regs + TB_ADDR_RX_DIAG_SIGDET_TUNE);
	writel(0x4041, regs + TB_ADDR_RX_DIAG_LFPSDET_TUNE2);
	writel(0x0480, regs + TB_ADDR_RX_DIAG_BS_TM);
	writel(0x8006, regs + TB_ADDR_RX_DIAG_DFE_CTRL1);
	writel(0x003f, regs + TB_ADDR_RX_DIAG_ILL_IQE_TRIM4);
	writel(0x543f, regs + TB_ADDR_RX_DIAG_ILL_E_TRIM0);
	writel(0x543f, regs + TB_ADDR_RX_DIAG_ILL_IQ_TRIM0);
	writel(0x0000, regs + TB_ADDR_RX_DIAG_ILL_IQE_TRIM6);
	writel(0x8000, regs + TB_ADDR_RX_DIAG_RXFE_TM3);
	writel(0x0003, regs + TB_ADDR_RX_DIAG_RXFE_TM4);
	writel(0x2408, regs + TB_ADDR_RX_DIAG_LFPSDET_TUNE);
	writel(0x05ca, regs + TB_ADDR_RX_DIAG_DFE_CTRL3);
	writel(0x0258, regs + TB_ADDR_RX_DIAG_SC2C_DELAY);
	writel(0x1fff, regs + TB_ADDR_RX_REE_VGA_GAIN_NODFE);

	writel(0x02c6, regs + TB_ADDR_XCVR_PSM_CAL_TMR);
	writel(0x0002, regs + TB_ADDR_XCVR_PSM_A0BYP_TMR);
	writel(0x02c6, regs + TB_ADDR_XCVR_PSM_A0IN_TMR);
	writel(0x0010, regs + TB_ADDR_XCVR_PSM_A1IN_TMR);
	writel(0x0010, regs + TB_ADDR_XCVR_PSM_A2IN_TMR);
	writel(0x0010, regs + TB_ADDR_XCVR_PSM_A3IN_TMR);
	writel(0x0010, regs + TB_ADDR_XCVR_PSM_A4IN_TMR);
	writel(0x0010, regs + TB_ADDR_XCVR_PSM_A5IN_TMR);

	writel(0x0002, regs + TB_ADDR_XCVR_PSM_A0OUT_TMR);
	writel(0x0002, regs + TB_ADDR_XCVR_PSM_A1OUT_TMR);
	writel(0x0002, regs + TB_ADDR_XCVR_PSM_A2OUT_TMR);
	writel(0x0002, regs + TB_ADDR_XCVR_PSM_A3OUT_TMR);
	writel(0x0002, regs + TB_ADDR_XCVR_PSM_A4OUT_TMR);
	writel(0x0002, regs + TB_ADDR_XCVR_PSM_A5OUT_TMR);

	/* Change rx detect parameter */
	writel(0x960, regs + TB_ADDR_TX_RCVDET_EN_TMR);
	writel(0x01e0, regs + TB_ADDR_TX_RCVDET_ST_TMR);
	writel(0x0090, regs + TB_ADDR_XCVR_DIAG_LANE_FCM_EN_MGN_TMR);

	/* RXDET_IN_P3_32KHZ, Receiver detect slow clock enable */
	value = readl(regs + TB_ADDR_TX_RCVDETSC_CTRL);
	value |= RXDET_IN_P3_32KHZ;
	writel(value, regs + TB_ADDR_TX_RCVDETSC_CTRL);

	udelay(10);

	pr_debug("end of %s\n", __func__);
}

static void cdns3_reset_core(struct cdns3 *cdns)
{
	u32 value;

	value = readl(cdns->none_core_regs + USB3_CORE_CTRL1);
	value |= ALL_SW_RESET;
	writel(value, cdns->none_core_regs + USB3_CORE_CTRL1);
	udelay(1);
}

static void cdns3_set_role(struct cdns3 *cdns, enum cdns3_roles role)
{
	u32 value;
	int timeout_us = 100000;

	if (role == CDNS3_ROLE_END)
		return;

	/* Wait clk value */
	value = readl(cdns->none_core_regs + USB3_SSPHY_STATUS);
	writel(value, cdns->none_core_regs + USB3_SSPHY_STATUS);
	udelay(1);
	value = readl(cdns->none_core_regs + USB3_SSPHY_STATUS);
	while ((value & 0xf0000000) != 0xf0000000 && timeout_us-- > 0) {
		value = readl(cdns->none_core_regs + USB3_SSPHY_STATUS);
		dev_dbg(cdns->dev, "clkvld:0x%x\n", value);
		udelay(1);
	}

	if (timeout_us <= 0)
		dev_err(cdns->dev, "wait clkvld timeout\n");

	/* Set all Reset bits */
	value = readl(cdns->none_core_regs + USB3_CORE_CTRL1);
	value |= ALL_SW_RESET;
	writel(value, cdns->none_core_regs + USB3_CORE_CTRL1);
	udelay(1);

	if (role == CDNS3_ROLE_HOST) {
		value = readl(cdns->none_core_regs + USB3_CORE_CTRL1);
		value = (value & ~MODE_STRAP_MASK) | HOST_MODE | OC_DISABLE;
		writel(value, cdns->none_core_regs + USB3_CORE_CTRL1);
		value &= ~PHYAHB_SW_RESET;
		writel(value, cdns->none_core_regs + USB3_CORE_CTRL1);
		mdelay(1);
		cdns3_usb_phy_init(cdns->phy_regs);
		/* Force B Session Valid as 1 */
		writel(0x0060, cdns->phy_regs + 0x380a4);
		mdelay(1);

		value = readl(cdns->none_core_regs + USB3_INT_REG);
		value |= HOST_INT1_EN;
		writel(value, cdns->none_core_regs + USB3_INT_REG);

		value = readl(cdns->none_core_regs + USB3_CORE_CTRL1);
		value &= ~ALL_SW_RESET;
		writel(value, cdns->none_core_regs + USB3_CORE_CTRL1);

		dev_dbg(cdns->dev, "wait xhci_power_on_ready\n");

		value = readl(cdns->none_core_regs + USB3_CORE_STATUS);
		timeout_us = 100000;
		while (!(value & HOST_POWER_ON_READY) && timeout_us-- > 0) {
			value = readl(cdns->none_core_regs + USB3_CORE_STATUS);
			udelay(1);
		}

		if (timeout_us <= 0)
			dev_err(cdns->dev, "wait xhci_power_on_ready timeout\n");

		mdelay(1);

		dev_dbg(cdns->dev, "switch to host role successfully\n");
	} else { /* gadget mode */
		value = readl(cdns->none_core_regs + USB3_CORE_CTRL1);
		value = (value & ~MODE_STRAP_MASK) | DEV_MODE;
		writel(value, cdns->none_core_regs + USB3_CORE_CTRL1);
		value &= ~PHYAHB_SW_RESET;
		writel(value, cdns->none_core_regs + USB3_CORE_CTRL1);

		cdns3_usb_phy_init(cdns->phy_regs);
		/* Force B Session Valid as 1 */
		writel(0x0060, cdns->phy_regs + 0x380a4);
		value = readl(cdns->none_core_regs + USB3_INT_REG);
		value |= DEV_INT_EN;
		writel(value, cdns->none_core_regs + USB3_INT_REG);

		value = readl(cdns->none_core_regs + USB3_CORE_CTRL1);
		value &= ~ALL_SW_RESET;
		writel(value, cdns->none_core_regs + USB3_CORE_CTRL1);

		dev_dbg(cdns->dev, "wait gadget_power_on_ready\n");

		value = readl(cdns->none_core_regs + USB3_CORE_STATUS);
		timeout_us = 100000;
		while (!(value & DEV_POWER_ON_READY) && timeout_us-- > 0) {
			value = readl(cdns->none_core_regs + USB3_CORE_STATUS);
			udelay(1);
		}

		if (timeout_us <= 0)
			dev_err(cdns->dev,
				"wait gadget_power_on_ready timeout\n");

		mdelay(1);

		dev_dbg(cdns->dev, "switch to gadget role successfully\n");
	}
}

static enum cdns3_roles cdns3_get_role(struct cdns3 *cdns)
{
	return cdns->roles[CDNS3_ROLE_HOST]
		? CDNS3_ROLE_HOST
		: CDNS3_ROLE_GADGET;
}

/**
 * cdns3_core_init_role - initialize role of operation
 * @cdns: Pointer to cdns3 structure
 *
 * Returns 0 on success otherwise negative errno
 */
static int cdns3_core_init_role(struct cdns3 *cdns, enum usb_dr_mode dr_mode)
{
	cdns->role = CDNS3_ROLE_END;
	if (dr_mode == USB_DR_MODE_UNKNOWN)
		dr_mode = USB_DR_MODE_OTG;

	/* Currently, only support gadget mode */
	if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_HOST) {
		dev_err(cdns->dev, "doesn't support host and OTG, only for gadget\n");
		return -EPERM;
	}

	if (dr_mode == USB_DR_MODE_PERIPHERAL) {
		if (cdns3_gadget_init(cdns))
			dev_info(cdns->dev, "doesn't support gadget\n");
	}

	if (!cdns->roles[CDNS3_ROLE_HOST] && !cdns->roles[CDNS3_ROLE_GADGET]) {
		dev_err(cdns->dev, "no supported roles\n");
		return -ENODEV;
	}

	return 0;
}

static void cdns3_remove_roles(struct cdns3 *cdns)
{
	/* Only support gadget */
	cdns3_gadget_remove(cdns);
}

int cdns3_uboot_init(struct cdns3_device *cdns3_dev)
{
	struct device *dev = NULL;
	struct cdns3 *cdns;
	int ret;

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

	cdns->dev = dev;

	/*
	 * Request memory region
	 * region-0: nxp wrap registers
	 * region-1: xHCI
	 * region-2: Peripheral
	 * region-3: PHY registers
	 * region-4: OTG registers
	 */
	cdns->none_core_regs = (void __iomem *)cdns3_dev->none_core_base;
	cdns->xhci_regs = (void __iomem *)cdns3_dev->xhci_base;
	cdns->dev_regs = (void __iomem *)cdns3_dev->dev_base;
	cdns->phy_regs = (void __iomem *)cdns3_dev->phy_base;
	cdns->otg_regs = (void __iomem *)cdns3_dev->otg_base;
	cdns->index = cdns3_dev->index;

	ret = cdns3_enable_clks(cdns->index);
	if (ret)
		return ret;

	ret = cdns3_core_init_role(cdns, cdns3_dev->dr_mode);
	if (ret)
		goto err1;

	cdns->role = cdns3_get_role(cdns);
	dev_dbg(dev, "the init role is %d\n", cdns->role);
	cdns3_set_role(cdns, cdns->role);
	ret = cdns3_role_start(cdns, cdns->role);
	if (ret) {
		dev_err(dev, "can't start %s role\n", cdns3_role(cdns)->name);
		goto err2;
	}

	dev_dbg(dev, "Cadence USB3 core: probe succeed\n");

	list_add_tail(&cdns->list, &cdns3_list);

	return 0;

err2:
	cdns3_remove_roles(cdns);
err1:
	cdns3_disable_clks(cdns->index);

	/* For u-boot, need to free the memory manually here. */
	if (cdns != NULL)
		free(cdns);

	return ret;
}

void cdns3_uboot_exit(int index)
{
	struct cdns3 *cdns;

	list_for_each_entry(cdns, &cdns3_list, list) {
		if (cdns->index != index)
			continue;

		cdns3_role_stop(cdns);
		cdns3_remove_roles(cdns);
		cdns3_reset_core(cdns);
		cdns3_disable_clks(index);

		list_del(&cdns->list);
		kfree(cdns);
		break;
	}
}

void cdns3_uboot_handle_interrupt(int index)
{
	struct cdns3 *cdns = NULL;

	list_for_each_entry(cdns, &cdns3_list, list) {
		if (cdns->index != index)
			continue;

		cdns3_role_irq_handler(cdns);
		break;
	}
}
