1 // SPDX-License-Identifier: GPL-2.0
3 * Greybus Vibrator protocol driver.
5 * Copyright 2014 Google Inc.
6 * Copyright 2014 Linaro Ltd.
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/slab.h>
12 #include <linux/device.h>
13 #include <linux/kdev_t.h>
14 #include <linux/idr.h>
15 #include <linux/pm_runtime.h>
19 struct gb_vibrator_device {
20 struct gb_connection *connection;
22 int minor; /* vibrator minor number */
23 struct delayed_work delayed_work;
26 /* Greybus Vibrator operation types */
27 #define GB_VIBRATOR_TYPE_ON 0x02
28 #define GB_VIBRATOR_TYPE_OFF 0x03
30 static int turn_off(struct gb_vibrator_device *vib)
32 struct gb_bundle *bundle = vib->connection->bundle;
35 ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_OFF,
38 gb_pm_runtime_put_autosuspend(bundle);
43 static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms)
45 struct gb_bundle *bundle = vib->connection->bundle;
48 ret = gb_pm_runtime_get_sync(bundle);
52 /* Vibrator was switched ON earlier */
53 if (cancel_delayed_work_sync(&vib->delayed_work))
56 ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_ON,
59 gb_pm_runtime_put_autosuspend(bundle);
63 schedule_delayed_work(&vib->delayed_work, msecs_to_jiffies(timeout_ms));
68 static void gb_vibrator_worker(struct work_struct *work)
70 struct delayed_work *delayed_work = to_delayed_work(work);
71 struct gb_vibrator_device *vib =
72 container_of(delayed_work,
73 struct gb_vibrator_device,
79 static ssize_t timeout_store(struct device *dev, struct device_attribute *attr,
80 const char *buf, size_t count)
82 struct gb_vibrator_device *vib = dev_get_drvdata(dev);
86 retval = kstrtoul(buf, 10, &val);
88 dev_err(dev, "could not parse timeout value %d\n", retval);
93 retval = turn_on(vib, (u16)val);
95 retval = turn_off(vib);
101 static DEVICE_ATTR_WO(timeout);
103 static struct attribute *vibrator_attrs[] = {
104 &dev_attr_timeout.attr,
107 ATTRIBUTE_GROUPS(vibrator);
109 static struct class vibrator_class = {
111 .owner = THIS_MODULE,
112 .dev_groups = vibrator_groups,
115 static DEFINE_IDA(minors);
117 static int gb_vibrator_probe(struct gb_bundle *bundle,
118 const struct greybus_bundle_id *id)
120 struct greybus_descriptor_cport *cport_desc;
121 struct gb_connection *connection;
122 struct gb_vibrator_device *vib;
126 if (bundle->num_cports != 1)
129 cport_desc = &bundle->cport_desc[0];
130 if (cport_desc->protocol_id != GREYBUS_PROTOCOL_VIBRATOR)
133 vib = kzalloc(sizeof(*vib), GFP_KERNEL);
137 connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id),
139 if (IS_ERR(connection)) {
140 retval = PTR_ERR(connection);
143 gb_connection_set_data(connection, vib);
145 vib->connection = connection;
147 greybus_set_drvdata(bundle, vib);
149 retval = gb_connection_enable(connection);
151 goto err_connection_destroy;
154 * For now we create a device in sysfs for the vibrator, but odds are
155 * there is a "real" device somewhere in the kernel for this, but I
156 * can't find it at the moment...
158 vib->minor = ida_simple_get(&minors, 0, 0, GFP_KERNEL);
159 if (vib->minor < 0) {
161 goto err_connection_disable;
163 dev = device_create(&vibrator_class, &bundle->dev,
164 MKDEV(0, 0), vib, "vibrator%d", vib->minor);
171 INIT_DELAYED_WORK(&vib->delayed_work, gb_vibrator_worker);
173 gb_pm_runtime_put_autosuspend(bundle);
178 ida_simple_remove(&minors, vib->minor);
179 err_connection_disable:
180 gb_connection_disable(connection);
181 err_connection_destroy:
182 gb_connection_destroy(connection);
189 static void gb_vibrator_disconnect(struct gb_bundle *bundle)
191 struct gb_vibrator_device *vib = greybus_get_drvdata(bundle);
194 ret = gb_pm_runtime_get_sync(bundle);
196 gb_pm_runtime_get_noresume(bundle);
198 if (cancel_delayed_work_sync(&vib->delayed_work))
201 device_unregister(vib->dev);
202 ida_simple_remove(&minors, vib->minor);
203 gb_connection_disable(vib->connection);
204 gb_connection_destroy(vib->connection);
208 static const struct greybus_bundle_id gb_vibrator_id_table[] = {
209 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_VIBRATOR) },
212 MODULE_DEVICE_TABLE(greybus, gb_vibrator_id_table);
214 static struct greybus_driver gb_vibrator_driver = {
216 .probe = gb_vibrator_probe,
217 .disconnect = gb_vibrator_disconnect,
218 .id_table = gb_vibrator_id_table,
221 static __init int gb_vibrator_init(void)
225 retval = class_register(&vibrator_class);
229 retval = greybus_register(&gb_vibrator_driver);
231 goto err_class_unregister;
235 err_class_unregister:
236 class_unregister(&vibrator_class);
240 module_init(gb_vibrator_init);
242 static __exit void gb_vibrator_exit(void)
244 greybus_deregister(&gb_vibrator_driver);
245 class_unregister(&vibrator_class);
246 ida_destroy(&minors);
248 module_exit(gb_vibrator_exit);
250 MODULE_LICENSE("GPL v2");