// 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@foss.st.com> for STMicroelectronics.
 */

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

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

DECLARE_GLOBAL_DATA_PTR;

/*
 * struct sti_dwc3_glue_plat - 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_plat {
	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_plat *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_plat *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_of_to_plat(struct udevice *dev)
{
	struct sti_dwc3_glue_plat *plat = dev_get_plat(dev);
	struct udevice *syscon;
	struct regmap *regmap;
	int ret;
	u32 reg[4];

	ret = ofnode_read_u32_array(dev_ofnode(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->ranges[0].start;

	/* 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_plat *plat = dev_get_plat(dev);
	ofnode node, dwc3_node;

	/* Find snps,dwc3 node from subnode */
	ofnode_for_each_subnode(node, dev_ofnode(dev)) {
		if (ofnode_device_is_compatible(node, "snps,dwc3"))
			dwc3_node = node;
	}

	if (!ofnode_valid(dwc3_node)) {
		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_plat *plat = dev_get_plat(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_plat *plat = dev_get_plat(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_NOP,
	.of_match = sti_dwc3_glue_ids,
	.of_to_plat = sti_dwc3_glue_of_to_plat,
	.probe = sti_dwc3_glue_probe,
	.remove = sti_dwc3_glue_remove,
	.bind = sti_dwc3_glue_bind,
	.plat_auto	= sizeof(struct sti_dwc3_glue_plat),
	.flags = DM_FLAG_ALLOC_PRIV_DMA,
};
