/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * Copyright (C) 2012 ARM Limited
 */

#define pr_fmt(fmt) "vexpress-config: " fmt

#include <linux/bitops.h>
#include <linux/completion.h>
#include <linux/export.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/vexpress.h>


#define VEXPRESS_CONFIG_MAX_BRIDGES 2

struct vexpress_config_bridge {
	struct device_node *node;
	struct vexpress_config_bridge_info *info;
	struct list_head transactions;
	spinlock_t transactions_lock;
} vexpress_config_bridges[VEXPRESS_CONFIG_MAX_BRIDGES];

static DECLARE_BITMAP(vexpress_config_bridges_map,
		ARRAY_SIZE(vexpress_config_bridges));
static DEFINE_MUTEX(vexpress_config_bridges_mutex);

struct vexpress_config_bridge *vexpress_config_bridge_register(
		struct device_node *node,
		struct vexpress_config_bridge_info *info)
{
	struct vexpress_config_bridge *bridge;
	int i;

	pr_debug("Registering bridge '%s'\n", info->name);

	mutex_lock(&vexpress_config_bridges_mutex);
	i = find_first_zero_bit(vexpress_config_bridges_map,
			ARRAY_SIZE(vexpress_config_bridges));
	if (i >= ARRAY_SIZE(vexpress_config_bridges)) {
		pr_err("Can't register more bridges!\n");
		mutex_unlock(&vexpress_config_bridges_mutex);
		return NULL;
	}
	__set_bit(i, vexpress_config_bridges_map);
	bridge = &vexpress_config_bridges[i];

	bridge->node = node;
	bridge->info = info;
	INIT_LIST_HEAD(&bridge->transactions);
	spin_lock_init(&bridge->transactions_lock);

	mutex_unlock(&vexpress_config_bridges_mutex);

	return bridge;
}
EXPORT_SYMBOL(vexpress_config_bridge_register);

void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge)
{
	struct vexpress_config_bridge __bridge = *bridge;
	int i;

	mutex_lock(&vexpress_config_bridges_mutex);
	for (i = 0; i < ARRAY_SIZE(vexpress_config_bridges); i++)
		if (&vexpress_config_bridges[i] == bridge)
			__clear_bit(i, vexpress_config_bridges_map);
	mutex_unlock(&vexpress_config_bridges_mutex);

	WARN_ON(!list_empty(&__bridge.transactions));
	while (!list_empty(&__bridge.transactions))
		cpu_relax();
}
EXPORT_SYMBOL(vexpress_config_bridge_unregister);


struct vexpress_config_func {
	struct vexpress_config_bridge *bridge;
	void *func;
};

struct vexpress_config_func *__vexpress_config_func_get(struct device *dev,
		struct device_node *node)
{
	struct device_node *bridge_node;
	struct vexpress_config_func *func;
	int i;

	if (WARN_ON(dev && node && dev->of_node != node))
		return NULL;
	if (dev && !node)
		node = dev->of_node;

	func = kzalloc(sizeof(*func), GFP_KERNEL);
	if (!func)
		return NULL;

	bridge_node = of_node_get(node);
	while (bridge_node) {
		const __be32 *prop = of_get_property(bridge_node,
				"arm,vexpress,config-bridge", NULL);

		if (prop) {
			bridge_node = of_find_node_by_phandle(
					be32_to_cpup(prop));
			break;
		}

		bridge_node = of_get_next_parent(bridge_node);
	}

	mutex_lock(&vexpress_config_bridges_mutex);
	for (i = 0; i < ARRAY_SIZE(vexpress_config_bridges); i++) {
		struct vexpress_config_bridge *bridge =
				&vexpress_config_bridges[i];

		if (test_bit(i, vexpress_config_bridges_map) &&
				bridge->node == bridge_node) {
			func->bridge = bridge;
			func->func = bridge->info->func_get(dev, node);
			break;
		}
	}
	mutex_unlock(&vexpress_config_bridges_mutex);

	if (!func->func) {
		of_node_put(node);
		kfree(func);
		return NULL;
	}

	return func;
}
EXPORT_SYMBOL(__vexpress_config_func_get);

void vexpress_config_func_put(struct vexpress_config_func *func)
{
	func->bridge->info->func_put(func->func);
	of_node_put(func->bridge->node);
	kfree(func);
}
EXPORT_SYMBOL(vexpress_config_func_put);

struct vexpress_config_trans {
	struct vexpress_config_func *func;
	int offset;
	bool write;
	u32 *data;
	int status;
	struct completion completion;
	struct list_head list;
};

static void vexpress_config_dump_trans(const char *what,
		struct vexpress_config_trans *trans)
{
	pr_debug("%s %s trans %p func 0x%p offset %d data 0x%x status %d\n",
			what, trans->write ? "write" : "read", trans,
			trans->func->func, trans->offset,
			trans->data ? *trans->data : 0, trans->status);
}

static int vexpress_config_schedule(struct vexpress_config_trans *trans)
{
	int status;
	struct vexpress_config_bridge *bridge = trans->func->bridge;
	unsigned long flags;

	init_completion(&trans->completion);
	trans->status = -EFAULT;

	spin_lock_irqsave(&bridge->transactions_lock, flags);

	if (list_empty(&bridge->transactions)) {
		vexpress_config_dump_trans("Executing", trans);
		status = bridge->info->func_exec(trans->func->func,
				trans->offset, trans->write, trans->data);
	} else {
		vexpress_config_dump_trans("Queuing", trans);
		status = VEXPRESS_CONFIG_STATUS_WAIT;
	}

	switch (status) {
	case VEXPRESS_CONFIG_STATUS_DONE:
		vexpress_config_dump_trans("Finished", trans);
		trans->status = status;
		break;
	case VEXPRESS_CONFIG_STATUS_WAIT:
		list_add_tail(&trans->list, &bridge->transactions);
		break;
	}

	spin_unlock_irqrestore(&bridge->transactions_lock, flags);

	return status;
}

void vexpress_config_complete(struct vexpress_config_bridge *bridge,
		int status)
{
	struct vexpress_config_trans *trans;
	unsigned long flags;
	const char *message = "Completed";

	spin_lock_irqsave(&bridge->transactions_lock, flags);

	trans = list_first_entry(&bridge->transactions,
			struct vexpress_config_trans, list);
	trans->status = status;

	do {
		vexpress_config_dump_trans(message, trans);
		list_del(&trans->list);
		complete(&trans->completion);

		if (list_empty(&bridge->transactions))
			break;

		trans = list_first_entry(&bridge->transactions,
				struct vexpress_config_trans, list);
		vexpress_config_dump_trans("Executing pending", trans);
		trans->status = bridge->info->func_exec(trans->func->func,
				trans->offset, trans->write, trans->data);
		message = "Finished pending";
	} while (trans->status == VEXPRESS_CONFIG_STATUS_DONE);

	spin_unlock_irqrestore(&bridge->transactions_lock, flags);
}
EXPORT_SYMBOL(vexpress_config_complete);

int vexpress_config_wait(struct vexpress_config_trans *trans)
{
	wait_for_completion(&trans->completion);

	return trans->status;
}
EXPORT_SYMBOL(vexpress_config_wait);

int vexpress_config_read(struct vexpress_config_func *func, int offset,
		u32 *data)
{
	struct vexpress_config_trans trans = {
		.func = func,
		.offset = offset,
		.write = false,
		.data = data,
		.status = 0,
	};
	int status = vexpress_config_schedule(&trans);

	if (status == VEXPRESS_CONFIG_STATUS_WAIT)
		status = vexpress_config_wait(&trans);

	return status;
}
EXPORT_SYMBOL(vexpress_config_read);

int vexpress_config_write(struct vexpress_config_func *func, int offset,
		u32 data)
{
	struct vexpress_config_trans trans = {
		.func = func,
		.offset = offset,
		.write = true,
		.data = &data,
		.status = 0,
	};
	int status = vexpress_config_schedule(&trans);

	if (status == VEXPRESS_CONFIG_STATUS_WAIT)
		status = vexpress_config_wait(&trans);

	return status;
}
EXPORT_SYMBOL(vexpress_config_write);
