/* MOXA ART Ethernet (RTL8201CP) MDIO interface driver
 *
 * Copyright (C) 2013 Jonas Jensen <jonas.jensen@gmail.com>
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2.  This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */

#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of_address.h>
#include <linux/of_mdio.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>

#define REG_PHY_CTRL            0
#define REG_PHY_WRITE_DATA      4

/* REG_PHY_CTRL */
#define MIIWR                   BIT(27) /* init write sequence (auto cleared)*/
#define MIIRD                   BIT(26)
#define REGAD_MASK              0x3e00000
#define PHYAD_MASK              0x1f0000
#define MIIRDATA_MASK           0xffff

/* REG_PHY_WRITE_DATA */
#define MIIWDATA_MASK           0xffff

struct moxart_mdio_data {
	void __iomem		*base;
};

static int moxart_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
{
	struct moxart_mdio_data *data = bus->priv;
	u32 ctrl = 0;
	unsigned int count = 5;

	dev_dbg(&bus->dev, "%s\n", __func__);

	ctrl |= MIIRD | ((mii_id << 16) & PHYAD_MASK) |
		((regnum << 21) & REGAD_MASK);

	writel(ctrl, data->base + REG_PHY_CTRL);

	do {
		ctrl = readl(data->base + REG_PHY_CTRL);

		if (!(ctrl & MIIRD))
			return ctrl & MIIRDATA_MASK;

		mdelay(10);
		count--;
	} while (count > 0);

	dev_dbg(&bus->dev, "%s timed out\n", __func__);

	return -ETIMEDOUT;
}

static int moxart_mdio_write(struct mii_bus *bus, int mii_id,
			     int regnum, u16 value)
{
	struct moxart_mdio_data *data = bus->priv;
	u32 ctrl = 0;
	unsigned int count = 5;

	dev_dbg(&bus->dev, "%s\n", __func__);

	ctrl |= MIIWR | ((mii_id << 16) & PHYAD_MASK) |
		((regnum << 21) & REGAD_MASK);

	value &= MIIWDATA_MASK;

	writel(value, data->base + REG_PHY_WRITE_DATA);
	writel(ctrl, data->base + REG_PHY_CTRL);

	do {
		ctrl = readl(data->base + REG_PHY_CTRL);

		if (!(ctrl & MIIWR))
			return 0;

		mdelay(10);
		count--;
	} while (count > 0);

	dev_dbg(&bus->dev, "%s timed out\n", __func__);

	return -ETIMEDOUT;
}

static int moxart_mdio_reset(struct mii_bus *bus)
{
	int data, i;

	for (i = 0; i < PHY_MAX_ADDR; i++) {
		data = moxart_mdio_read(bus, i, MII_BMCR);
		if (data < 0)
			continue;

		data |= BMCR_RESET;
		if (moxart_mdio_write(bus, i, MII_BMCR, data) < 0)
			continue;
	}

	return 0;
}

static int moxart_mdio_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct mii_bus *bus;
	struct moxart_mdio_data *data;
	struct resource *res;
	int ret, i;

	bus = mdiobus_alloc_size(sizeof(*data));
	if (!bus)
		return -ENOMEM;

	bus->name = "MOXA ART Ethernet MII";
	bus->read = &moxart_mdio_read;
	bus->write = &moxart_mdio_write;
	bus->reset = &moxart_mdio_reset;
	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d-mii", pdev->name, pdev->id);
	bus->parent = &pdev->dev;

	bus->irq = devm_kzalloc(&pdev->dev, sizeof(int) * PHY_MAX_ADDR,
			GFP_KERNEL);
	if (!bus->irq) {
		ret = -ENOMEM;
		goto err_out_free_mdiobus;
	}

	/* Setting PHY_IGNORE_INTERRUPT here even if it has no effect,
	 * of_mdiobus_register() sets these PHY_POLL.
	 * Ideally, the interrupt from MAC controller could be used to
	 * detect link state changes, not polling, i.e. if there was
	 * a way phy_driver could set PHY_HAS_INTERRUPT but have that
	 * interrupt handled in ethernet drivercode.
	 */
	for (i = 0; i < PHY_MAX_ADDR; i++)
		bus->irq[i] = PHY_IGNORE_INTERRUPT;

	data = bus->priv;
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	data->base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(data->base)) {
		ret = PTR_ERR(data->base);
		goto err_out_free_mdiobus;
	}

	ret = of_mdiobus_register(bus, np);
	if (ret < 0)
		goto err_out_free_mdiobus;

	platform_set_drvdata(pdev, bus);

	return 0;

err_out_free_mdiobus:
	mdiobus_free(bus);
	return ret;
}

static int moxart_mdio_remove(struct platform_device *pdev)
{
	struct mii_bus *bus = platform_get_drvdata(pdev);

	mdiobus_unregister(bus);
	mdiobus_free(bus);

	return 0;
}

static const struct of_device_id moxart_mdio_dt_ids[] = {
	{ .compatible = "moxa,moxart-mdio" },
	{ }
};
MODULE_DEVICE_TABLE(of, moxart_mdio_dt_ids);

static struct platform_driver moxart_mdio_driver = {
	.probe = moxart_mdio_probe,
	.remove = moxart_mdio_remove,
	.driver = {
		.name = "moxart-mdio",
		.of_match_table = moxart_mdio_dt_ids,
	},
};

module_platform_driver(moxart_mdio_driver);

MODULE_DESCRIPTION("MOXA ART MDIO interface driver");
MODULE_AUTHOR("Jonas Jensen <jonas.jensen@gmail.com>");
MODULE_LICENSE("GPL");
