mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2025-04-21 12:27:27 +03:00
[ifxmips]
* adds a rewrite of the tapi drivers + sip app. this is the result of lars' gsoc 2010 project, Thanks ! git-svn-id: svn://svn.openwrt.org/openwrt/trunk@23840 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
130
package/lqtapi/src/mps/vmmc-module.c
Normal file
130
package/lqtapi/src/mps/vmmc-module.c
Normal file
@@ -0,0 +1,130 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <asm/bitops.h>
|
||||
|
||||
#include "vmmc-module.h"
|
||||
|
||||
int vmmc_module_init(struct vmmc_module *module, size_t num_pins,
|
||||
const struct vmmc_module_ops *ops)
|
||||
{
|
||||
module->pins = kcalloc(num_pins, sizeof(*module->pins), GFP_KERNEL);
|
||||
|
||||
if (!module->pins)
|
||||
return -ENOMEM;
|
||||
|
||||
module->num_pins = num_pins;
|
||||
module->ops = ops;
|
||||
|
||||
mutex_init(&module->lock);
|
||||
module->refcount = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vmmc_module_sync(struct vmmc_module *module)
|
||||
{
|
||||
if (!test_and_clear_bit(VMMC_MODULE_FLAG_MODIFIED, &module->flags))
|
||||
return 0;
|
||||
|
||||
return module->ops->sync(module);
|
||||
}
|
||||
|
||||
int vmmc_module_get_pin(struct vmmc_module *module)
|
||||
{
|
||||
size_t i = 0;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; i < module->num_pins; ++i) {
|
||||
if (!test_and_set_bit(VMMC_MODULE_FLAG_PIN_USED(i), &module->flags))
|
||||
break;
|
||||
}
|
||||
if (i == module->num_pins)
|
||||
ret = -EBUSY;
|
||||
else
|
||||
ret = i;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void vmmc_module_put_pin(struct vmmc_module *module, unsigned int pin)
|
||||
{
|
||||
module->pins[pin] = 0;
|
||||
clear_bit(VMMC_MODULE_FLAG_PIN_USED(pin), &module->flags);
|
||||
}
|
||||
|
||||
void vmmc_module_set_pin_input(struct vmmc_module *module, unsigned int pin,
|
||||
struct vmmc_module *input)
|
||||
{
|
||||
if (input)
|
||||
module->pins[pin] = input->id;
|
||||
else
|
||||
module->pins[pin] = 0;
|
||||
|
||||
set_bit(VMMC_MODULE_FLAG_MODIFIED, &module->flags);
|
||||
}
|
||||
|
||||
static void vmmc_module_enable(struct vmmc_module *module)
|
||||
{
|
||||
mutex_lock(&module->lock);
|
||||
|
||||
if (++module->refcount == 1)
|
||||
module->ops->enable(module, true);
|
||||
|
||||
mutex_unlock(&module->lock);
|
||||
}
|
||||
|
||||
static void vmmc_module_disable(struct vmmc_module *module)
|
||||
{
|
||||
mutex_lock(&module->lock);
|
||||
|
||||
if (module->refcount <= 0)
|
||||
printk(KERN_ERR "vmmc module: unbalanced disable\n");
|
||||
else if (--module->refcount == 0)
|
||||
module->ops->enable(module, false);
|
||||
|
||||
mutex_unlock(&module->lock);
|
||||
}
|
||||
|
||||
|
||||
unsigned int vmmc_link_init(struct vmmc_link *link,
|
||||
struct vmmc_module *a, struct vmmc_module *b)
|
||||
{
|
||||
link->pins[0] = vmmc_module_get_pin(a);
|
||||
link->pins[1] = vmmc_module_get_pin(b);
|
||||
link->modules[0] = a;
|
||||
link->modules[1] = b;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vmmc_link_put(struct vmmc_link *link)
|
||||
{
|
||||
vmmc_link_disable(link);
|
||||
vmmc_module_sync(link->modules[0]);
|
||||
vmmc_module_sync(link->modules[1]);
|
||||
vmmc_module_put_pin(link->modules[0], link->pins[0]);
|
||||
vmmc_module_put_pin(link->modules[1], link->pins[1]);
|
||||
}
|
||||
|
||||
void vmmc_link_enable(struct vmmc_link *link)
|
||||
{
|
||||
vmmc_module_set_pin_input(link->modules[0], link->pins[0],
|
||||
link->modules[1]);
|
||||
vmmc_module_set_pin_input(link->modules[1], link->pins[1],
|
||||
link->modules[0]);
|
||||
|
||||
vmmc_module_enable(link->modules[0]);
|
||||
vmmc_module_enable(link->modules[1]);
|
||||
}
|
||||
|
||||
void vmmc_link_disable(struct vmmc_link *link)
|
||||
{
|
||||
vmmc_module_set_pin_input(link->modules[0], link->pins[0], NULL);
|
||||
vmmc_module_set_pin_input(link->modules[1], link->pins[1], NULL);
|
||||
|
||||
vmmc_module_disable(link->modules[0]);
|
||||
vmmc_module_disable(link->modules[1]);
|
||||
}
|
||||
Reference in New Issue
Block a user