// SPDX-License-Identifier: GPL-2.0+
/*
 * STiH407 family DWC3 specific Glue layer
 *
 * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
 * Author(s): Patrice Chotard, <patrice.chotard@st.com> for STMicroelectronics.
 */

#include <common.h>
#include <asm/io.h>
#include <dm.h>
#include <errno.h>
#include <fdtdec.h>
#include <linux/libfdt.h>
#include <dm/lists.h>
#include <regmap.h>
#include <reset-uclass.h>
#include <syscon.h>
#include <usb.h>

#include <linux/usb/dwc3.h>
#include <linux/usb/otg.h>
#include <dwc3-sti-glue.h>

DECLARE_GLOBAL_DATA_PTR;

/*
 * struct sti_dwc3_glue_platdata - dwc3 STi glue driver private structure
 * @syscfg_base:	addr for the glue syscfg
 * @glue_base:		addr for the glue registers
 * @syscfg_offset:	usb syscfg control offset
 * @powerdown_ctl:	rest controller for powerdown signal
 * @softreset_ctl:	reset controller for softreset signal
 * @mode:		drd static host/device config
 */
struct sti_dwc3_glue_platdata {
	phys_addr_t syscfg_base;
	phys_addr_t glue_base;
	phys_addr_t syscfg_offset;
	struct reset_ctl powerdown_ctl;
	struct reset_ctl softreset_ctl;
	enum usb_dr_mode mode;
};

static int sti_dwc3_glue_drd_init(struct sti_dwc3_glue_platdata *plat)
{
	unsigned long val;

	val = readl(plat->syscfg_base + plat->syscfg_offset);

	val &= USB3_CONTROL_MASK;

	switch (plat->mode) {
	case USB_DR_MODE_PERIPHERAL:
		val &= ~(USB3_DELAY_VBUSVALID
			| USB3_SEL_FORCE_OPMODE | USB3_FORCE_OPMODE(0x3)
			| USB3_SEL_FORCE_DPPULLDOWN2 | USB3_FORCE_DPPULLDOWN2
			| USB3_SEL_FORCE_DMPULLDOWN2 | USB3_FORCE_DMPULLDOWN2);

		val |= USB3_DEVICE_NOT_HOST | USB3_FORCE_VBUSVALID;
		break;

	case USB_DR_MODE_HOST:
		val &= ~(USB3_DEVICE_NOT_HOST | USB3_FORCE_VBUSVALID
			| USB3_SEL_FORCE_OPMODE	| USB3_FORCE_OPMODE(0x3)
			| USB3_SEL_FORCE_DPPULLDOWN2 | USB3_FORCE_DPPULLDOWN2
			| USB3_SEL_FORCE_DMPULLDOWN2 | USB3_FORCE_DMPULLDOWN2);

		val |= USB3_DELAY_VBUSVALID;
		break;

	default:
		pr_err("Unsupported mode of operation %d\n", plat->mode);
		return -EINVAL;
	}
	writel(val, plat->syscfg_base + plat->syscfg_offset);

	return 0;
}

static void sti_dwc3_glue_init(struct sti_dwc3_glue_platdata *plat)
{
	unsigned long reg;

	reg = readl(plat->glue_base + CLKRST_CTRL);

	reg |= AUX_CLK_EN | EXT_CFG_RESET_N | XHCI_REVISION;
	reg &= ~SW_PIPEW_RESET_N;

	writel(reg, plat->glue_base + CLKRST_CTRL);

	/* configure mux for vbus, powerpresent and bvalid signals */
	reg = readl(plat->glue_base + USB2_VBUS_MNGMNT_SEL1);

	reg |= SEL_OVERRIDE_VBUSVALID(USB2_VBUS_UTMIOTG) |
	       SEL_OVERRIDE_POWERPRESENT(USB2_VBUS_UTMIOTG) |
	       SEL_OVERRIDE_BVALID(USB2_VBUS_UTMIOTG);

	writel(reg, plat->glue_base + USB2_VBUS_MNGMNT_SEL1);

	setbits_le32(plat->glue_base + CLKRST_CTRL, SW_PIPEW_RESET_N);
}

static int sti_dwc3_glue_ofdata_to_platdata(struct udevice *dev)
{
	struct sti_dwc3_glue_platdata *plat = dev_get_platdata(dev);
	struct udevice *syscon;
	struct regmap *regmap;
	int ret;
	u32 reg[4];

	ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev),
				   "reg", reg, ARRAY_SIZE(reg));
	if (ret) {
		pr_err("unable to find st,stih407-dwc3 reg property(%d)\n", ret);
		return ret;
	}

	plat->glue_base = reg[0];
	plat->syscfg_offset = reg[2];

	/* get corresponding syscon phandle */
	ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "st,syscfg",
					   &syscon);
	if (ret) {
		pr_err("unable to find syscon device (%d)\n", ret);
		return ret;
	}

	/* get syscfg-reg base address */
	regmap = syscon_get_regmap(syscon);
	if (!regmap) {
		pr_err("unable to find regmap\n");
		return -ENODEV;
	}
	plat->syscfg_base = regmap->base;

	/* get powerdown reset */
	ret = reset_get_by_name(dev, "powerdown", &plat->powerdown_ctl);
	if (ret) {
		pr_err("can't get powerdown reset for %s (%d)", dev->name, ret);
		return ret;
	}

	/* get softreset reset */
	ret = reset_get_by_name(dev, "softreset", &plat->softreset_ctl);
	if (ret)
		pr_err("can't get soft reset for %s (%d)", dev->name, ret);

	return ret;
};

static int sti_dwc3_glue_bind(struct udevice *dev)
{
	struct sti_dwc3_glue_platdata *plat = dev_get_platdata(dev);
	int dwc3_node;

	/* check if one subnode is present */
	dwc3_node = fdt_first_subnode(gd->fdt_blob, dev_of_offset(dev));
	if (dwc3_node <= 0) {
		pr_err("Can't find subnode for %s\n", dev->name);
		return -ENODEV;
	}

	/* check if the subnode compatible string is the dwc3 one*/
	if (fdt_node_check_compatible(gd->fdt_blob, dwc3_node,
				      "snps,dwc3") != 0) {
		pr_err("Can't find dwc3 subnode for %s\n", dev->name);
		return -ENODEV;
	}

	/* retrieve the DWC3 dual role mode */
	plat->mode = usb_get_dr_mode(dwc3_node);
	if (plat->mode == USB_DR_MODE_UNKNOWN)
		/* by default set dual role mode to HOST */
		plat->mode = USB_DR_MODE_HOST;

	return dm_scan_fdt_dev(dev);
}

static int sti_dwc3_glue_probe(struct udevice *dev)
{
	struct sti_dwc3_glue_platdata *plat = dev_get_platdata(dev);
	int ret;

	/* deassert both powerdown and softreset */
	ret = reset_deassert(&plat->powerdown_ctl);
	if (ret < 0) {
		pr_err("DWC3 powerdown reset deassert failed: %d", ret);
		return ret;
	}

	ret = reset_deassert(&plat->softreset_ctl);
	if (ret < 0) {
		pr_err("DWC3 soft reset deassert failed: %d", ret);
		goto softreset_err;
	}

	ret = sti_dwc3_glue_drd_init(plat);
	if (ret)
		goto init_err;

	sti_dwc3_glue_init(plat);

	return 0;

init_err:
	ret = reset_assert(&plat->softreset_ctl);
	if (ret < 0) {
		pr_err("DWC3 soft reset deassert failed: %d", ret);
		return ret;
	}

softreset_err:
	ret = reset_assert(&plat->powerdown_ctl);
	if (ret < 0)
		pr_err("DWC3 powerdown reset deassert failed: %d", ret);

	return ret;
}

static int sti_dwc3_glue_remove(struct udevice *dev)
{
	struct sti_dwc3_glue_platdata *plat = dev_get_platdata(dev);
	int ret;

	/* assert both powerdown and softreset */
	ret = reset_assert(&plat->powerdown_ctl);
	if (ret < 0) {
		pr_err("DWC3 powerdown reset deassert failed: %d", ret);
		return ret;
	}

	ret = reset_assert(&plat->softreset_ctl);
	if (ret < 0)
		pr_err("DWC3 soft reset deassert failed: %d", ret);

	return ret;
}

static const struct udevice_id sti_dwc3_glue_ids[] = {
	{ .compatible = "st,stih407-dwc3" },
	{ }
};

U_BOOT_DRIVER(dwc3_sti_glue) = {
	.name = "dwc3_sti_glue",
	.id = UCLASS_MISC,
	.of_match = sti_dwc3_glue_ids,
	.ofdata_to_platdata = sti_dwc3_glue_ofdata_to_platdata,
	.probe = sti_dwc3_glue_probe,
	.remove = sti_dwc3_glue_remove,
	.bind = sti_dwc3_glue_bind,
	.platdata_auto_alloc_size = sizeof(struct sti_dwc3_glue_platdata),
	.flags = DM_FLAG_ALLOC_PRIV_DMA,
};
