// SPDX-License-Identifier: GPL-2.0+
/*
 * ENETC ethernet controller driver
 * Copyright 2019 NXP
 */

#include <common.h>
#include <dm.h>
#include <errno.h>
#include <pci.h>
#include <miiphy.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <miiphy.h>

#include "fsl_enetc.h"

static void enetc_mdio_wait_bsy(struct enetc_mdio_priv *priv)
{
	while (enetc_read(priv, ENETC_MDIO_CFG) & ENETC_EMDIO_CFG_BSY)
		cpu_relax();
}

static int enetc_mdio_read_priv(struct enetc_mdio_priv *priv, int addr,
				int devad, int reg)
{
	if (devad == MDIO_DEVAD_NONE)
		enetc_write(priv, ENETC_MDIO_CFG, ENETC_EMDIO_CFG_C22);
	else
		enetc_write(priv, ENETC_MDIO_CFG, ENETC_EMDIO_CFG_C45);
	enetc_mdio_wait_bsy(priv);

	if (devad == MDIO_DEVAD_NONE) {
		enetc_write(priv, ENETC_MDIO_CTL, ENETC_MDIO_CTL_READ |
			    (addr << 5) | reg);
	} else {
		enetc_write(priv, ENETC_MDIO_CTL, (addr << 5) + devad);
		enetc_mdio_wait_bsy(priv);

		enetc_write(priv, ENETC_MDIO_STAT, reg);
		enetc_mdio_wait_bsy(priv);

		enetc_write(priv, ENETC_MDIO_CTL, ENETC_MDIO_CTL_READ |
			    (addr << 5) | devad);
	}

	enetc_mdio_wait_bsy(priv);
	if (enetc_read(priv, ENETC_MDIO_CFG) & ENETC_EMDIO_CFG_RD_ER)
		return ENETC_MDIO_READ_ERR;

	return enetc_read(priv, ENETC_MDIO_DATA);
}

static int enetc_mdio_write_priv(struct enetc_mdio_priv *priv, int addr,
				 int devad, int reg, u16 val)
{
	if (devad == MDIO_DEVAD_NONE)
		enetc_write(priv, ENETC_MDIO_CFG, ENETC_EMDIO_CFG_C22);
	else
		enetc_write(priv, ENETC_MDIO_CFG, ENETC_EMDIO_CFG_C45);
	enetc_mdio_wait_bsy(priv);

	if (devad != MDIO_DEVAD_NONE) {
		enetc_write(priv, ENETC_MDIO_CTL, (addr << 5) + devad);
		enetc_write(priv, ENETC_MDIO_STAT, reg);
	} else {
		enetc_write(priv, ENETC_MDIO_CTL, (addr << 5) + reg);
	}
	enetc_mdio_wait_bsy(priv);

	enetc_write(priv, ENETC_MDIO_DATA, val);
	enetc_mdio_wait_bsy(priv);

	return 0;
}

/* DM wrappers */
static int dm_enetc_mdio_read(struct udevice *dev, int addr, int devad, int reg)
{
	struct enetc_mdio_priv *priv = dev_get_priv(dev);

	return enetc_mdio_read_priv(priv, addr, devad, reg);
}

static int dm_enetc_mdio_write(struct udevice *dev, int addr, int devad,
			       int reg, u16 val)
{
	struct enetc_mdio_priv *priv = dev_get_priv(dev);

	return enetc_mdio_write_priv(priv, addr, devad, reg, val);
}

static const struct mdio_ops enetc_mdio_ops = {
	.read = dm_enetc_mdio_read,
	.write = dm_enetc_mdio_write,
};

static int enetc_mdio_bind(struct udevice *dev)
{
	char name[16];
	static int eth_num_devices;

	/*
	 * prefer using PCI function numbers to number interfaces, but these
	 * are only available if dts nodes are present.  For PCI they are
	 * optional, handle that case too.  Just in case some nodes are present
	 * and some are not, use different naming scheme - enetc-N based on
	 * PCI function # and enetc#N based on interface count
	 */
	if (ofnode_valid(dev->node))
		sprintf(name, "emdio-%u", PCI_FUNC(pci_get_devfn(dev)));
	else
		sprintf(name, "emdio#%u", eth_num_devices++);
	device_set_name(dev, name);

	return 0;
}

static int enetc_mdio_probe(struct udevice *dev)
{
	struct enetc_mdio_priv *priv = dev_get_priv(dev);

	priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0);
	if (!priv->regs_base) {
		enetc_dbg(dev, "failed to map BAR0\n");
		return -EINVAL;
	}

	priv->regs_base += ENETC_MDIO_BASE;

	dm_pci_clrset_config16(dev, PCI_COMMAND, 0, PCI_COMMAND_MEMORY);

	return 0;
}

U_BOOT_DRIVER(enetc_mdio) = {
	.name	= "enetc_mdio",
	.id	= UCLASS_MDIO,
	.bind	= enetc_mdio_bind,
	.probe	= enetc_mdio_probe,
	.ops	= &enetc_mdio_ops,
	.priv_auto_alloc_size = sizeof(struct enetc_mdio_priv),
};

static struct pci_device_id enetc_mdio_ids[] = {
	{ PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVICE_ID_ENETC_MDIO) },
};

U_BOOT_PCI_DEVICE(enetc_mdio, enetc_mdio_ids);
