/*
 * Greybus "Core"
 *
 * Copyright 2014-2015 Google Inc.
 * Copyright 2014-2015 Linaro Ltd.
 *
 * Released under the GPLv2 only.
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#define CREATE_TRACE_POINTS
#include "firmware.h"
#include "greybus.h"
#include "greybus_trace.h"
#include "legacy.h"

EXPORT_TRACEPOINT_SYMBOL_GPL(gb_host_device_send);
EXPORT_TRACEPOINT_SYMBOL_GPL(gb_host_device_recv);

/* Allow greybus to be disabled at boot if needed */
static bool nogreybus;
#ifdef MODULE
module_param(nogreybus, bool, 0444);
#else
core_param(nogreybus, nogreybus, bool, 0444);
#endif
int greybus_disabled(void)
{
	return nogreybus;
}
EXPORT_SYMBOL_GPL(greybus_disabled);

static int greybus_match_one_id(struct gb_bundle *bundle,
				     const struct greybus_bundle_id *id)
{
	if ((id->match_flags & GREYBUS_ID_MATCH_VENDOR) &&
	    (id->vendor != bundle->intf->vendor_id))
		return 0;

	if ((id->match_flags & GREYBUS_ID_MATCH_PRODUCT) &&
	    (id->product != bundle->intf->product_id))
		return 0;

	if ((id->match_flags & GREYBUS_ID_MATCH_CLASS) &&
	    (id->class != bundle->class))
		return 0;

	return 1;
}

static const struct greybus_bundle_id *
greybus_match_id(struct gb_bundle *bundle, const struct greybus_bundle_id *id)
{
	if (id == NULL)
		return NULL;

	for (; id->vendor || id->product || id->class || id->driver_info;
									id++) {
		if (greybus_match_one_id(bundle, id))
			return id;
	}

	return NULL;
}

static int greybus_module_match(struct device *dev, struct device_driver *drv)
{
	struct greybus_driver *driver = to_greybus_driver(drv);
	struct gb_bundle *bundle;
	const struct greybus_bundle_id *id;

	if (!is_gb_bundle(dev))
		return 0;

	bundle = to_gb_bundle(dev);

	id = greybus_match_id(bundle, driver->id_table);
	if (id)
		return 1;
	/* FIXME - Dynamic ids? */
	return 0;
}

static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env)
{
	struct gb_host_device *hd;
	struct gb_interface *intf = NULL;
	struct gb_bundle *bundle = NULL;
	struct gb_svc *svc = NULL;

	if (is_gb_host_device(dev)) {
		hd = to_gb_host_device(dev);
	} else if (is_gb_interface(dev)) {
		intf = to_gb_interface(dev);
		hd = intf->hd;
	} else if (is_gb_bundle(dev)) {
		bundle = to_gb_bundle(dev);
		intf = bundle->intf;
		hd = intf->hd;
	} else if (is_gb_svc(dev)) {
		svc = to_gb_svc(dev);
		hd = svc->hd;
	} else {
		dev_WARN(dev, "uevent for unknown greybus device \"type\"!\n");
		return -EINVAL;
	}

	if (add_uevent_var(env, "BUS=%u", hd->bus_id))
		return -ENOMEM;

	if (intf) {
		if (add_uevent_var(env, "INTERFACE=%u", intf->interface_id))
			return -ENOMEM;
		if (add_uevent_var(env, "GREYBUS_ID=%04x/%04x",
				   (u16)(intf->vendor_id & 0xffff),
				   (u16)(intf->product_id & 0xffff)))
			return -ENOMEM;
	}

	if (bundle) {
		// FIXME
		// add a uevent that can "load" a bundle type
		// This is what we need to bind a driver to so use the info
		// in gmod here as well

		if (add_uevent_var(env, "BUNDLE=%u", bundle->id))
			return -ENOMEM;
		if (add_uevent_var(env, "BUNDLE_CLASS=%02x", bundle->class))
			return -ENOMEM;
	}

	return 0;
}

struct bus_type greybus_bus_type = {
	.name =		"greybus",
	.match =	greybus_module_match,
	.uevent =	greybus_uevent,
};

static int greybus_probe(struct device *dev)
{
	struct greybus_driver *driver = to_greybus_driver(dev->driver);
	struct gb_bundle *bundle = to_gb_bundle(dev);
	const struct greybus_bundle_id *id;
	int retval;

	/* match id */
	id = greybus_match_id(bundle, driver->id_table);
	if (!id)
		return -ENODEV;

	retval = driver->probe(bundle, id);
	if (retval) {
		/*
		 * Catch buggy drivers that fail to destroy their connections.
		 */
		WARN_ON(!list_empty(&bundle->connections));

		return retval;
	}

	return 0;
}

static int greybus_remove(struct device *dev)
{
	struct greybus_driver *driver = to_greybus_driver(dev->driver);
	struct gb_bundle *bundle = to_gb_bundle(dev);
	struct gb_connection *connection;

	list_for_each_entry(connection, &bundle->connections, bundle_links) {
		if (bundle->intf->disconnected)
			gb_connection_disable(connection);
		else
			gb_connection_disable_rx(connection);
	}

	driver->disconnect(bundle);

	/* Catch buggy drivers that fail to destroy their connections. */
	WARN_ON(!list_empty(&bundle->connections));

	return 0;
}

int greybus_register_driver(struct greybus_driver *driver, struct module *owner,
		const char *mod_name)
{
	int retval;

	if (greybus_disabled())
		return -ENODEV;

	driver->driver.bus = &greybus_bus_type;
	driver->driver.name = driver->name;
	driver->driver.probe = greybus_probe;
	driver->driver.remove = greybus_remove;
	driver->driver.owner = owner;
	driver->driver.mod_name = mod_name;

	retval = driver_register(&driver->driver);
	if (retval)
		return retval;

	pr_info("registered new driver %s\n", driver->name);
	return 0;
}
EXPORT_SYMBOL_GPL(greybus_register_driver);

void greybus_deregister_driver(struct greybus_driver *driver)
{
	driver_unregister(&driver->driver);
}
EXPORT_SYMBOL_GPL(greybus_deregister_driver);

static int __init gb_init(void)
{
	int retval;

	if (greybus_disabled())
		return -ENODEV;

	BUILD_BUG_ON(CPORT_ID_MAX >= (long)CPORT_ID_BAD);

	gb_debugfs_init();

	retval = bus_register(&greybus_bus_type);
	if (retval) {
		pr_err("bus_register failed (%d)\n", retval);
		goto error_bus;
	}

	retval = gb_hd_init();
	if (retval) {
		pr_err("gb_hd_init failed (%d)\n", retval);
		goto error_hd;
	}

	retval = gb_operation_init();
	if (retval) {
		pr_err("gb_operation_init failed (%d)\n", retval);
		goto error_operation;
	}

	retval = gb_firmware_init();
	if (retval) {
		pr_err("gb_firmware_init failed\n");
		goto error_firmware;
	}

	retval = gb_legacy_init();
	if (retval) {
		pr_err("gb_legacy_init failed\n");
		goto error_legacy;
	}

	return 0;	/* Success */

error_legacy:
	gb_firmware_exit();
error_firmware:
	gb_operation_exit();
error_operation:
	gb_hd_exit();
error_hd:
	bus_unregister(&greybus_bus_type);
error_bus:
	gb_debugfs_cleanup();

	return retval;
}
module_init(gb_init);

static void __exit gb_exit(void)
{
	gb_legacy_exit();
	gb_firmware_exit();
	gb_operation_exit();
	gb_hd_exit();
	bus_unregister(&greybus_bus_type);
	gb_debugfs_cleanup();
	tracepoint_synchronize_unregister();
}
module_exit(gb_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@linuxfoundation.org>");
