/*
 * Copyright 2015,2016 Freescale Semiconductor, Inc.
 *
 * FSL USB HOST xHCI Controller
 *
 * Author: Ramneek Mehresh<ramneek.mehresh@freescale.com>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <usb.h>
#include <linux/errno.h>
#include <linux/compat.h>
#include <linux/usb/xhci-fsl.h>
#include <linux/usb/dwc3.h>
#include "xhci.h"
#include <fsl_errata.h>
#include <fsl_usb.h>
#include <dm.h>

/* Declare global data pointer */
DECLARE_GLOBAL_DATA_PTR;

#ifndef CONFIG_DM_USB
static struct fsl_xhci fsl_xhci;
unsigned long ctr_addr[] = FSL_USB_XHCI_ADDR;
#else
struct xhci_fsl_priv {
	struct xhci_ctrl xhci;
	fdt_addr_t hcd_base;
	struct fsl_xhci ctx;
};
#endif

__weak int __board_usb_init(int index, enum usb_init_type init)
{
	return 0;
}

static int erratum_a008751(void)
{
#if defined(CONFIG_TARGET_LS2080AQDS) || defined(CONFIG_TARGET_LS2080ARDB)
	u32 __iomem *scfg = (u32 __iomem *)SCFG_BASE;
	writel(SCFG_USB3PRM1CR_INIT, scfg + SCFG_USB3PRM1CR / 4);
	return 0;
#endif
	return 1;
}

static void fsl_apply_xhci_errata(void)
{
	int ret;
	if (has_erratum_a008751()) {
		ret = erratum_a008751();
		if (ret != 0)
			puts("Failed to apply erratum a008751\n");
	}
}

static void fsl_xhci_set_beat_burst_length(struct dwc3 *dwc3_reg)
{
	clrsetbits_le32(&dwc3_reg->g_sbuscfg0, USB3_ENABLE_BEAT_BURST_MASK,
			USB3_ENABLE_BEAT_BURST);
	setbits_le32(&dwc3_reg->g_sbuscfg1, USB3_SET_BEAT_BURST_LIMIT);
}

static int fsl_xhci_core_init(struct fsl_xhci *fsl_xhci)
{
	int ret = 0;

	ret = dwc3_core_init(fsl_xhci->dwc3_reg);
	if (ret) {
		debug("%s:failed to initialize core\n", __func__);
		return ret;
	}

	/* We are hard-coding DWC3 core to Host Mode */
	dwc3_set_mode(fsl_xhci->dwc3_reg, DWC3_GCTL_PRTCAP_HOST);

	/* Set GFLADJ_30MHZ as 20h as per XHCI spec default value */
	dwc3_set_fladj(fsl_xhci->dwc3_reg, GFLADJ_30MHZ_DEFAULT);

	/* Change beat burst and outstanding pipelined transfers requests */
	fsl_xhci_set_beat_burst_length(fsl_xhci->dwc3_reg);

	return ret;
}

static int fsl_xhci_core_exit(struct fsl_xhci *fsl_xhci)
{
	/*
	 * Currently fsl socs do not support PHY shutdown from
	 * sw. But this support may be added in future socs.
	 */
	return 0;
}

#ifdef CONFIG_DM_USB
static int xhci_fsl_probe(struct udevice *dev)
{
	struct xhci_fsl_priv *priv = dev_get_priv(dev);
	struct xhci_hccr *hccr;
	struct xhci_hcor *hcor;

	int ret = 0;

	/*
	 * Get the base address for XHCI controller from the device node
	 */
	priv->hcd_base = dev_get_addr(dev);
	if (priv->hcd_base == FDT_ADDR_T_NONE) {
		debug("Can't get the XHCI register base address\n");
		return -ENXIO;
	}
	priv->ctx.hcd = (struct xhci_hccr *)priv->hcd_base;
	priv->ctx.dwc3_reg = (struct dwc3 *)((char *)(priv->hcd_base) +
			  DWC3_REG_OFFSET);

	fsl_apply_xhci_errata();

	ret = fsl_xhci_core_init(&priv->ctx);
	if (ret < 0) {
		puts("Failed to initialize xhci\n");
		return ret;
	}

	hccr = (struct xhci_hccr *)(priv->ctx.hcd);
	hcor = (struct xhci_hcor *)((uintptr_t) hccr
				+ HC_LENGTH(xhci_readl(&hccr->cr_capbase)));

	debug("xhci-fsl: init hccr %lx and hcor %lx hc_length %lx\n",
	      (uintptr_t)hccr, (uintptr_t)hcor,
	      (uintptr_t)HC_LENGTH(xhci_readl(&hccr->cr_capbase)));

	return xhci_register(dev, hccr, hcor);
}

static int xhci_fsl_remove(struct udevice *dev)
{
	struct xhci_fsl_priv *priv = dev_get_priv(dev);

	fsl_xhci_core_exit(&priv->ctx);

	return xhci_deregister(dev);
}

static const struct udevice_id xhci_usb_ids[] = {
	{ .compatible = "fsl,layerscape-dwc3", },
	{ }
};

U_BOOT_DRIVER(xhci_fsl) = {
	.name	= "xhci_fsl",
	.id	= UCLASS_USB,
	.of_match = xhci_usb_ids,
	.probe = xhci_fsl_probe,
	.remove = xhci_fsl_remove,
	.ops	= &xhci_usb_ops,
	.platdata_auto_alloc_size = sizeof(struct usb_platdata),
	.priv_auto_alloc_size = sizeof(struct xhci_fsl_priv),
	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
};
#else
int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor)
{
	struct fsl_xhci *ctx = &fsl_xhci;
	int ret = 0;

	ctx->hcd = (struct xhci_hccr *)ctr_addr[index];
	ctx->dwc3_reg = (struct dwc3 *)((char *)(ctx->hcd) + DWC3_REG_OFFSET);

	ret = board_usb_init(index, USB_INIT_HOST);
	if (ret != 0) {
		puts("Failed to initialize board for USB\n");
		return ret;
	}

	fsl_apply_xhci_errata();

	ret = fsl_xhci_core_init(ctx);
	if (ret < 0) {
		puts("Failed to initialize xhci\n");
		return ret;
	}

	*hccr = (struct xhci_hccr *)ctx->hcd;
	*hcor = (struct xhci_hcor *)((uintptr_t) *hccr
				+ HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase)));

	debug("fsl-xhci: init hccr %lx and hcor %lx hc_length %lx\n",
	      (uintptr_t)*hccr, (uintptr_t)*hcor,
	      (uintptr_t)HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase)));

	return ret;
}

void xhci_hcd_stop(int index)
{
	struct fsl_xhci *ctx = &fsl_xhci;

	fsl_xhci_core_exit(ctx);
}
#endif
