1 #include <linux/module.h>
2 #include <linux/kernel.h>
3 #include <linux/slab.h>
4 #include <linux/mutex.h>
6 #include <asm/bitops.h>
8 #include "vmmc-module.h"
10 int vmmc_module_init(struct vmmc_module *module, size_t num_pins,
11 const struct vmmc_module_ops *ops)
13 module->pins = kcalloc(num_pins, sizeof(*module->pins), GFP_KERNEL);
18 module->num_pins = num_pins;
21 mutex_init(&module->lock);
27 int vmmc_module_sync(struct vmmc_module *module)
29 if (!test_and_clear_bit(VMMC_MODULE_FLAG_MODIFIED, &module->flags))
32 return module->ops->sync(module);
35 int vmmc_module_get_pin(struct vmmc_module *module)
40 for (i = 0; i < module->num_pins; ++i) {
41 if (!test_and_set_bit(VMMC_MODULE_FLAG_PIN_USED(i), &module->flags))
44 if (i == module->num_pins)
52 void vmmc_module_put_pin(struct vmmc_module *module, unsigned int pin)
54 module->pins[pin] = 0;
55 clear_bit(VMMC_MODULE_FLAG_PIN_USED(pin), &module->flags);
58 void vmmc_module_set_pin_input(struct vmmc_module *module, unsigned int pin,
59 struct vmmc_module *input)
62 module->pins[pin] = input->id;
64 module->pins[pin] = 0;
66 set_bit(VMMC_MODULE_FLAG_MODIFIED, &module->flags);
69 static void vmmc_module_enable(struct vmmc_module *module)
71 mutex_lock(&module->lock);
73 if (++module->refcount == 1)
74 module->ops->enable(module, true);
76 mutex_unlock(&module->lock);
79 static void vmmc_module_disable(struct vmmc_module *module)
81 mutex_lock(&module->lock);
83 if (module->refcount <= 0)
84 printk(KERN_ERR "vmmc module: unbalanced disable\n");
85 else if (--module->refcount == 0)
86 module->ops->enable(module, false);
88 mutex_unlock(&module->lock);
92 unsigned int vmmc_link_init(struct vmmc_link *link,
93 struct vmmc_module *a, struct vmmc_module *b)
95 link->pins[0] = vmmc_module_get_pin(a);
96 link->pins[1] = vmmc_module_get_pin(b);
103 void vmmc_link_put(struct vmmc_link *link)
105 vmmc_link_disable(link);
106 vmmc_module_sync(link->modules[0]);
107 vmmc_module_sync(link->modules[1]);
108 vmmc_module_put_pin(link->modules[0], link->pins[0]);
109 vmmc_module_put_pin(link->modules[1], link->pins[1]);
112 void vmmc_link_enable(struct vmmc_link *link)
114 vmmc_module_set_pin_input(link->modules[0], link->pins[0],
116 vmmc_module_set_pin_input(link->modules[1], link->pins[1],
119 vmmc_module_enable(link->modules[0]);
120 vmmc_module_enable(link->modules[1]);
123 void vmmc_link_disable(struct vmmc_link *link)
125 vmmc_module_set_pin_input(link->modules[0], link->pins[0], NULL);
126 vmmc_module_set_pin_input(link->modules[1], link->pins[1], NULL);
128 vmmc_module_disable(link->modules[0]);
129 vmmc_module_disable(link->modules[1]);