diff options
Diffstat (limited to 'drivers/mfd/vexpress-config.c')
| -rw-r--r-- | drivers/mfd/vexpress-config.c | 288 | 
1 files changed, 0 insertions, 288 deletions
diff --git a/drivers/mfd/vexpress-config.c b/drivers/mfd/vexpress-config.c deleted file mode 100644 index 84ce6b9daa3..00000000000 --- a/drivers/mfd/vexpress-config.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * 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);  | 
