/*
 * Distributed Switch Architecture loopback driver
 *
 * Copyright (C) 2016, Florian Fainelli <f.fainelli@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include <linux/platform_device.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
#include <linux/phy_fixed.h>
#include <linux/export.h>
#include <linux/workqueue.h>
#include <linux/module.h>
#include <linux/if_bridge.h>
#include <net/switchdev.h>
#include <net/dsa.h>

#include "dsa_loop.h"

struct dsa_loop_vlan {
	u16 members;
	u16 untagged;
};

#define DSA_LOOP_VLANS	5

struct dsa_loop_priv {
	struct mii_bus	*bus;
	unsigned int	port_base;
	struct dsa_loop_vlan vlans[DSA_LOOP_VLANS];
	struct net_device *netdev;
	u16 pvid;
};

static struct phy_device *phydevs[PHY_MAX_ADDR];

static enum dsa_tag_protocol dsa_loop_get_protocol(struct dsa_switch *ds)
{
	dev_dbg(ds->dev, "%s\n", __func__);

	return DSA_TAG_PROTO_NONE;
}

static int dsa_loop_setup(struct dsa_switch *ds)
{
	dev_dbg(ds->dev, "%s\n", __func__);

	return 0;
}

static int dsa_loop_set_addr(struct dsa_switch *ds, u8 *addr)
{
	dev_dbg(ds->dev, "%s\n", __func__);

	return 0;
}

static int dsa_loop_phy_read(struct dsa_switch *ds, int port, int regnum)
{
	struct dsa_loop_priv *ps = ds->priv;
	struct mii_bus *bus = ps->bus;

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

	return mdiobus_read_nested(bus, ps->port_base + port, regnum);
}

static int dsa_loop_phy_write(struct dsa_switch *ds, int port,
			      int regnum, u16 value)
{
	struct dsa_loop_priv *ps = ds->priv;
	struct mii_bus *bus = ps->bus;

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

	return mdiobus_write_nested(bus, ps->port_base + port, regnum, value);
}

static int dsa_loop_port_bridge_join(struct dsa_switch *ds, int port,
				     struct net_device *bridge)
{
	dev_dbg(ds->dev, "%s\n", __func__);

	return 0;
}

static void dsa_loop_port_bridge_leave(struct dsa_switch *ds, int port,
				       struct net_device *bridge)
{
	dev_dbg(ds->dev, "%s\n", __func__);
}

static void dsa_loop_port_stp_state_set(struct dsa_switch *ds, int port,
					u8 state)
{
	dev_dbg(ds->dev, "%s\n", __func__);
}

static int dsa_loop_port_vlan_filtering(struct dsa_switch *ds, int port,
					bool vlan_filtering)
{
	dev_dbg(ds->dev, "%s\n", __func__);

	return 0;
}

static int dsa_loop_port_vlan_prepare(struct dsa_switch *ds, int port,
				      const struct switchdev_obj_port_vlan *vlan,
				      struct switchdev_trans *trans)
{
	struct dsa_loop_priv *ps = ds->priv;
	struct mii_bus *bus = ps->bus;

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

	/* Just do a sleeping operation to make lockdep checks effective */
	mdiobus_read(bus, ps->port_base + port, MII_BMSR);

	if (vlan->vid_end > DSA_LOOP_VLANS)
		return -ERANGE;

	return 0;
}

static void dsa_loop_port_vlan_add(struct dsa_switch *ds, int port,
				   const struct switchdev_obj_port_vlan *vlan,
				   struct switchdev_trans *trans)
{
	bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
	bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
	struct dsa_loop_priv *ps = ds->priv;
	struct mii_bus *bus = ps->bus;
	struct dsa_loop_vlan *vl;
	u16 vid;

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

	/* Just do a sleeping operation to make lockdep checks effective */
	mdiobus_read(bus, ps->port_base + port, MII_BMSR);

	for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
		vl = &ps->vlans[vid];

		vl->members |= BIT(port);
		if (untagged)
			vl->untagged |= BIT(port);
		else
			vl->untagged &= ~BIT(port);
	}

	if (pvid)
		ps->pvid = vid;
}

static int dsa_loop_port_vlan_del(struct dsa_switch *ds, int port,
				  const struct switchdev_obj_port_vlan *vlan)
{
	bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
	struct dsa_loop_priv *ps = ds->priv;
	struct mii_bus *bus = ps->bus;
	struct dsa_loop_vlan *vl;
	u16 vid, pvid;

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

	/* Just do a sleeping operation to make lockdep checks effective */
	mdiobus_read(bus, ps->port_base + port, MII_BMSR);

	for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
		vl = &ps->vlans[vid];

		vl->members &= ~BIT(port);
		if (untagged)
			vl->untagged &= ~BIT(port);

		if (pvid == vid)
			pvid = 1;
	}
	ps->pvid = pvid;

	return 0;
}

static int dsa_loop_port_vlan_dump(struct dsa_switch *ds, int port,
				   struct switchdev_obj_port_vlan *vlan,
				   int (*cb)(struct switchdev_obj *obj))
{
	struct dsa_loop_priv *ps = ds->priv;
	struct mii_bus *bus = ps->bus;
	struct dsa_loop_vlan *vl;
	u16 vid, vid_start = 0;
	int err;

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

	/* Just do a sleeping operation to make lockdep checks effective */
	mdiobus_read(bus, ps->port_base + port, MII_BMSR);

	for (vid = vid_start; vid < DSA_LOOP_VLANS; vid++) {
		vl = &ps->vlans[vid];

		if (!(vl->members & BIT(port)))
			continue;

		vlan->vid_begin = vlan->vid_end = vid;
		vlan->flags = 0;

		if (vl->untagged & BIT(port))
			vlan->flags |= BRIDGE_VLAN_INFO_UNTAGGED;
		if (ps->pvid == vid)
			vlan->flags |= BRIDGE_VLAN_INFO_PVID;

		err = cb(&vlan->obj);
		if (err)
			break;
	}

	return err;
}

static struct dsa_switch_ops dsa_loop_driver = {
	.get_tag_protocol	= dsa_loop_get_protocol,
	.setup			= dsa_loop_setup,
	.set_addr		= dsa_loop_set_addr,
	.phy_read		= dsa_loop_phy_read,
	.phy_write		= dsa_loop_phy_write,
	.port_bridge_join	= dsa_loop_port_bridge_join,
	.port_bridge_leave	= dsa_loop_port_bridge_leave,
	.port_stp_state_set	= dsa_loop_port_stp_state_set,
	.port_vlan_filtering	= dsa_loop_port_vlan_filtering,
	.port_vlan_prepare	= dsa_loop_port_vlan_prepare,
	.port_vlan_add		= dsa_loop_port_vlan_add,
	.port_vlan_del		= dsa_loop_port_vlan_del,
	.port_vlan_dump		= dsa_loop_port_vlan_dump,
};

static int dsa_loop_drv_probe(struct mdio_device *mdiodev)
{
	struct dsa_loop_pdata *pdata = mdiodev->dev.platform_data;
	struct dsa_loop_priv *ps;
	struct dsa_switch *ds;

	if (!pdata)
		return -ENODEV;

	dev_info(&mdiodev->dev, "%s: 0x%0x\n",
		 pdata->name, pdata->enabled_ports);

	ds = dsa_switch_alloc(&mdiodev->dev, DSA_MAX_PORTS);
	if (!ds)
		return -ENOMEM;

	ps = devm_kzalloc(&mdiodev->dev, sizeof(*ps), GFP_KERNEL);
	ps->netdev = dev_get_by_name(&init_net, pdata->netdev);
	if (!ps->netdev)
		return -EPROBE_DEFER;

	pdata->cd.netdev[DSA_LOOP_CPU_PORT] = &ps->netdev->dev;

	ds->dev = &mdiodev->dev;
	ds->ops = &dsa_loop_driver;
	ds->priv = ps;
	ps->bus = mdiodev->bus;

	dev_set_drvdata(&mdiodev->dev, ds);

	return dsa_register_switch(ds, ds->dev);
}

static void dsa_loop_drv_remove(struct mdio_device *mdiodev)
{
	struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
	struct dsa_loop_priv *ps = ds->priv;

	dsa_unregister_switch(ds);
	dev_put(ps->netdev);
}

static struct mdio_driver dsa_loop_drv = {
	.mdiodrv.driver	= {
		.name	= "dsa-loop",
	},
	.probe	= dsa_loop_drv_probe,
	.remove	= dsa_loop_drv_remove,
};

#define NUM_FIXED_PHYS	(DSA_LOOP_NUM_PORTS - 2)

static void unregister_fixed_phys(void)
{
	unsigned int i;

	for (i = 0; i < NUM_FIXED_PHYS; i++)
		if (phydevs[i])
			fixed_phy_unregister(phydevs[i]);
}

static int __init dsa_loop_init(void)
{
	struct fixed_phy_status status = {
		.link = 1,
		.speed = SPEED_100,
		.duplex = DUPLEX_FULL,
	};
	unsigned int i;

	for (i = 0; i < NUM_FIXED_PHYS; i++)
		phydevs[i] = fixed_phy_register(PHY_POLL, &status, -1, NULL);

	return mdio_driver_register(&dsa_loop_drv);
}
module_init(dsa_loop_init);

static void __exit dsa_loop_exit(void)
{
	mdio_driver_unregister(&dsa_loop_drv);
	unregister_fixed_phys();
}
module_exit(dsa_loop_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Florian Fainelli");
MODULE_DESCRIPTION("DSA loopback driver");
