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]);