// SPDX-License-Identifier: GPL-2.0
/*
 * T-HEAD DWMAC platform driver
 *
 * Copyright (C) 2021 Alibaba Group Holding Limited.
 * Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org>
 *
 */

#include <linux/bitfield.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_net.h>
#include <linux/platform_device.h>

#include "stmmac_platform.h"

#define GMAC_CLK_EN			0x00
#define  GMAC_TX_CLK_EN			BIT(1)
#define  GMAC_TX_CLK_N_EN		BIT(2)
#define  GMAC_TX_CLK_OUT_EN		BIT(3)
#define  GMAC_RX_CLK_EN			BIT(4)
#define  GMAC_RX_CLK_N_EN		BIT(5)
#define  GMAC_EPHY_REF_CLK_EN		BIT(6)
#define GMAC_RXCLK_DELAY_CTRL		0x04
#define  GMAC_RXCLK_BYPASS		BIT(15)
#define  GMAC_RXCLK_INVERT		BIT(14)
#define  GMAC_RXCLK_DELAY		GENMASK(4, 0)
#define GMAC_TXCLK_DELAY_CTRL		0x08
#define  GMAC_TXCLK_BYPASS		BIT(15)
#define  GMAC_TXCLK_INVERT		BIT(14)
#define  GMAC_TXCLK_DELAY		GENMASK(4, 0)
#define GMAC_PLLCLK_DIV			0x0c
#define  GMAC_PLLCLK_DIV_EN		BIT(31)
#define  GMAC_PLLCLK_DIV_NUM		GENMASK(7, 0)
#define GMAC_GTXCLK_SEL			0x18
#define  GMAC_GTXCLK_SEL_PLL		BIT(0)
#define GMAC_INTF_CTRL			0x1c
#define  PHY_INTF_MASK			BIT(0)
#define  PHY_INTF_RGMII			FIELD_PREP(PHY_INTF_MASK, 1)
#define  PHY_INTF_MII_GMII		FIELD_PREP(PHY_INTF_MASK, 0)
#define GMAC_TXCLK_OEN			0x20
#define  TXCLK_DIR_MASK			BIT(0)
#define  TXCLK_DIR_OUTPUT		FIELD_PREP(TXCLK_DIR_MASK, 0)
#define  TXCLK_DIR_INPUT		FIELD_PREP(TXCLK_DIR_MASK, 1)

struct thead_dwmac {
	struct plat_stmmacenet_data *plat;
	void __iomem *apb_base;
	struct device *dev;
};

static int thead_dwmac_set_phy_if(struct plat_stmmacenet_data *plat)
{
	struct thead_dwmac *dwmac = plat->bsp_priv;
	u32 phyif;

	switch (plat->phy_interface) {
	case PHY_INTERFACE_MODE_MII:
		phyif = PHY_INTF_MII_GMII;
		break;
	case PHY_INTERFACE_MODE_RGMII:
	case PHY_INTERFACE_MODE_RGMII_ID:
	case PHY_INTERFACE_MODE_RGMII_TXID:
	case PHY_INTERFACE_MODE_RGMII_RXID:
		phyif = PHY_INTF_RGMII;
		break;
	default:
		dev_err(dwmac->dev, "unsupported phy interface %s\n",
			phy_modes(plat->phy_interface));
		return -EINVAL;
	}

	writel(phyif, dwmac->apb_base + GMAC_INTF_CTRL);
	return 0;
}

static int thead_dwmac_set_txclk_dir(struct plat_stmmacenet_data *plat)
{
	struct thead_dwmac *dwmac = plat->bsp_priv;
	u32 txclk_dir;

	switch (plat->phy_interface) {
	case PHY_INTERFACE_MODE_MII:
		txclk_dir = TXCLK_DIR_INPUT;
		break;
	case PHY_INTERFACE_MODE_RGMII:
	case PHY_INTERFACE_MODE_RGMII_ID:
	case PHY_INTERFACE_MODE_RGMII_TXID:
	case PHY_INTERFACE_MODE_RGMII_RXID:
		txclk_dir = TXCLK_DIR_OUTPUT;
		break;
	default:
		dev_err(dwmac->dev, "unsupported phy interface %s\n",
			phy_modes(plat->phy_interface));
		return -EINVAL;
	}

	writel(txclk_dir, dwmac->apb_base + GMAC_TXCLK_OEN);
	return 0;
}

static int thead_set_clk_tx_rate(void *bsp_priv, struct clk *clk_tx_i,
				 phy_interface_t interface, int speed)
{
	struct thead_dwmac *dwmac = bsp_priv;
	struct plat_stmmacenet_data *plat;
	unsigned long rate;
	long tx_rate;
	u32 div, reg;

	plat = dwmac->plat;

	switch (plat->phy_interface) {
	/* For MII, rxc/txc is provided by phy */
	case PHY_INTERFACE_MODE_MII:
		return 0;

	case PHY_INTERFACE_MODE_RGMII:
	case PHY_INTERFACE_MODE_RGMII_ID:
	case PHY_INTERFACE_MODE_RGMII_RXID:
	case PHY_INTERFACE_MODE_RGMII_TXID:
		rate = clk_get_rate(plat->stmmac_clk);

		writel(0, dwmac->apb_base + GMAC_PLLCLK_DIV);

		tx_rate = rgmii_clock(speed);
		if (tx_rate < 0) {
			dev_err(dwmac->dev, "invalid speed %d\n", speed);
			return tx_rate;
		}

		div = rate / tx_rate;
		if (rate != tx_rate * div) {
			dev_err(dwmac->dev, "invalid gmac rate %lu\n", rate);
			return -EINVAL;
		}

		reg = FIELD_PREP(GMAC_PLLCLK_DIV_EN, 1) |
		      FIELD_PREP(GMAC_PLLCLK_DIV_NUM, div);
		writel(reg, dwmac->apb_base + GMAC_PLLCLK_DIV);
		return 0;

	default:
		dev_err(dwmac->dev, "unsupported phy interface %s\n",
			phy_modes(plat->phy_interface));
		return -EINVAL;
	}
}

static int thead_dwmac_enable_clk(struct plat_stmmacenet_data *plat)
{
	struct thead_dwmac *dwmac = plat->bsp_priv;
	u32 reg, div;

	switch (plat->phy_interface) {
	case PHY_INTERFACE_MODE_MII:
		reg = GMAC_RX_CLK_EN | GMAC_TX_CLK_EN;
		break;

	case PHY_INTERFACE_MODE_RGMII:
	case PHY_INTERFACE_MODE_RGMII_ID:
	case PHY_INTERFACE_MODE_RGMII_RXID:
	case PHY_INTERFACE_MODE_RGMII_TXID:
		/* use pll */
		div = clk_get_rate(plat->stmmac_clk) / rgmii_clock(SPEED_1000);
		reg = FIELD_PREP(GMAC_PLLCLK_DIV_EN, 1) |
		      FIELD_PREP(GMAC_PLLCLK_DIV_NUM, div);

		writel(0, dwmac->apb_base + GMAC_PLLCLK_DIV);
		writel(reg, dwmac->apb_base + GMAC_PLLCLK_DIV);

		writel(GMAC_GTXCLK_SEL_PLL, dwmac->apb_base + GMAC_GTXCLK_SEL);
		reg = GMAC_TX_CLK_EN | GMAC_TX_CLK_N_EN | GMAC_TX_CLK_OUT_EN |
		      GMAC_RX_CLK_EN | GMAC_RX_CLK_N_EN;
		break;

	default:
		dev_err(dwmac->dev, "unsupported phy interface %s\n",
			phy_modes(plat->phy_interface));
		return -EINVAL;
	}

	writel(reg, dwmac->apb_base + GMAC_CLK_EN);
	return 0;
}

static int thead_dwmac_init(struct platform_device *pdev, void *priv)
{
	struct thead_dwmac *dwmac = priv;
	unsigned int reg;
	int ret;

	ret = thead_dwmac_set_phy_if(dwmac->plat);
	if (ret)
		return ret;

	ret = thead_dwmac_set_txclk_dir(dwmac->plat);
	if (ret)
		return ret;

	reg = readl(dwmac->apb_base + GMAC_RXCLK_DELAY_CTRL);
	reg &= ~(GMAC_RXCLK_DELAY);
	reg |= FIELD_PREP(GMAC_RXCLK_DELAY, 0);
	writel(reg, dwmac->apb_base + GMAC_RXCLK_DELAY_CTRL);

	reg = readl(dwmac->apb_base + GMAC_TXCLK_DELAY_CTRL);
	reg &= ~(GMAC_TXCLK_DELAY);
	reg |= FIELD_PREP(GMAC_TXCLK_DELAY, 0);
	writel(reg, dwmac->apb_base + GMAC_TXCLK_DELAY_CTRL);

	return thead_dwmac_enable_clk(dwmac->plat);
}

static int thead_dwmac_probe(struct platform_device *pdev)
{
	struct stmmac_resources stmmac_res;
	struct plat_stmmacenet_data *plat;
	struct thead_dwmac *dwmac;
	struct clk *apb_clk;
	void __iomem *apb;
	int ret;

	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
	if (ret)
		return dev_err_probe(&pdev->dev, ret,
				     "failed to get resources\n");

	plat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);
	if (IS_ERR(plat))
		return dev_err_probe(&pdev->dev, PTR_ERR(plat),
				     "dt configuration failed\n");

	/*
	 * The APB clock is essential for accessing glue registers. However,
	 * old devicetrees don't describe it correctly. We continue to probe
	 * and emit a warning if it isn't present.
	 */
	apb_clk = devm_clk_get_enabled(&pdev->dev, "apb");
	if (PTR_ERR(apb_clk) == -ENOENT)
		dev_warn(&pdev->dev,
			 "cannot get apb clock, link may break after speed changes\n");
	else if (IS_ERR(apb_clk))
		return dev_err_probe(&pdev->dev, PTR_ERR(apb_clk),
				     "failed to get apb clock\n");

	dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
	if (!dwmac)
		return -ENOMEM;

	apb = devm_platform_ioremap_resource(pdev, 1);
	if (IS_ERR(apb))
		return dev_err_probe(&pdev->dev, PTR_ERR(apb),
				     "failed to remap gmac apb registers\n");

	dwmac->dev = &pdev->dev;
	dwmac->plat = plat;
	dwmac->apb_base = apb;
	plat->bsp_priv = dwmac;
	plat->set_clk_tx_rate = thead_set_clk_tx_rate;
	plat->init = thead_dwmac_init;

	return devm_stmmac_pltfr_probe(pdev, plat, &stmmac_res);
}

static const struct of_device_id thead_dwmac_match[] = {
	{ .compatible = "thead,th1520-gmac" },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, thead_dwmac_match);

static struct platform_driver thead_dwmac_driver = {
	.probe = thead_dwmac_probe,
	.driver = {
		.name = "thead-dwmac",
		.pm = &stmmac_pltfr_pm_ops,
		.of_match_table = thead_dwmac_match,
	},
};
module_platform_driver(thead_dwmac_driver);

MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>");
MODULE_AUTHOR("Drew Fustini <drew@pdp7.com>");
MODULE_DESCRIPTION("T-HEAD DWMAC platform driver");
MODULE_LICENSE("GPL");
