Linux-libre 4.9.30-gnu
[librecmc/linux-libre.git] / drivers / staging / greybus / vibrator.c
1 /*
2  * Greybus Vibrator protocol driver.
3  *
4  * Copyright 2014 Google Inc.
5  * Copyright 2014 Linaro Ltd.
6  *
7  * Released under the GPLv2 only.
8  */
9
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/slab.h>
13 #include <linux/device.h>
14 #include <linux/kdev_t.h>
15 #include <linux/idr.h>
16 #include <linux/pm_runtime.h>
17
18 #include "greybus.h"
19
20 struct gb_vibrator_device {
21         struct gb_connection    *connection;
22         struct device           *dev;
23         int                     minor;          /* vibrator minor number */
24         struct delayed_work     delayed_work;
25 };
26
27 /* Greybus Vibrator operation types */
28 #define GB_VIBRATOR_TYPE_ON                     0x02
29 #define GB_VIBRATOR_TYPE_OFF                    0x03
30
31 static int turn_off(struct gb_vibrator_device *vib)
32 {
33         struct gb_bundle *bundle = vib->connection->bundle;
34         int ret;
35
36         ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_OFF,
37                         NULL, 0, NULL, 0);
38
39         gb_pm_runtime_put_autosuspend(bundle);
40
41         return ret;
42 }
43
44 static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms)
45 {
46         struct gb_bundle *bundle = vib->connection->bundle;
47         int ret;
48
49         ret = gb_pm_runtime_get_sync(bundle);
50         if (ret)
51                 return ret;
52
53         /* Vibrator was switched ON earlier */
54         if (cancel_delayed_work_sync(&vib->delayed_work))
55                 turn_off(vib);
56
57         ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_ON,
58                         NULL, 0, NULL, 0);
59         if (ret) {
60                 gb_pm_runtime_put_autosuspend(bundle);
61                 return ret;
62         }
63
64         schedule_delayed_work(&vib->delayed_work, msecs_to_jiffies(timeout_ms));
65
66         return 0;
67 }
68
69 static void gb_vibrator_worker(struct work_struct *work)
70 {
71         struct delayed_work *delayed_work = to_delayed_work(work);
72         struct gb_vibrator_device *vib =
73                 container_of(delayed_work, struct gb_vibrator_device, delayed_work);
74
75         turn_off(vib);
76 }
77
78 static ssize_t timeout_store(struct device *dev, struct device_attribute *attr,
79                              const char *buf, size_t count)
80 {
81         struct gb_vibrator_device *vib = dev_get_drvdata(dev);
82         unsigned long val;
83         int retval;
84
85         retval = kstrtoul(buf, 10, &val);
86         if (retval < 0) {
87                 dev_err(dev, "could not parse timeout value %d\n", retval);
88                 return retval;
89         }
90
91         if (val)
92                 retval = turn_on(vib, (u16)val);
93         else
94                 retval = turn_off(vib);
95         if (retval)
96                 return retval;
97
98         return count;
99 }
100 static DEVICE_ATTR_WO(timeout);
101
102 static struct attribute *vibrator_attrs[] = {
103         &dev_attr_timeout.attr,
104         NULL,
105 };
106 ATTRIBUTE_GROUPS(vibrator);
107
108 static struct class vibrator_class = {
109         .name           = "vibrator",
110         .owner          = THIS_MODULE,
111         .dev_groups     = vibrator_groups,
112 };
113
114 static DEFINE_IDA(minors);
115
116 static int gb_vibrator_probe(struct gb_bundle *bundle,
117                                         const struct greybus_bundle_id *id)
118 {
119         struct greybus_descriptor_cport *cport_desc;
120         struct gb_connection *connection;
121         struct gb_vibrator_device *vib;
122         struct device *dev;
123         int retval;
124
125         if (bundle->num_cports != 1)
126                 return -ENODEV;
127
128         cport_desc = &bundle->cport_desc[0];
129         if (cport_desc->protocol_id != GREYBUS_PROTOCOL_VIBRATOR)
130                 return -ENODEV;
131
132         vib = kzalloc(sizeof(*vib), GFP_KERNEL);
133         if (!vib)
134                 return -ENOMEM;
135
136         connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id),
137                                                 NULL);
138         if (IS_ERR(connection)) {
139                 retval = PTR_ERR(connection);
140                 goto err_free_vib;
141         }
142         gb_connection_set_data(connection, vib);
143
144         vib->connection = connection;
145
146         greybus_set_drvdata(bundle, vib);
147
148         retval = gb_connection_enable(connection);
149         if (retval)
150                 goto err_connection_destroy;
151
152         /*
153          * For now we create a device in sysfs for the vibrator, but odds are
154          * there is a "real" device somewhere in the kernel for this, but I
155          * can't find it at the moment...
156          */
157         vib->minor = ida_simple_get(&minors, 0, 0, GFP_KERNEL);
158         if (vib->minor < 0) {
159                 retval = vib->minor;
160                 goto err_connection_disable;
161         }
162         dev = device_create(&vibrator_class, &bundle->dev,
163                             MKDEV(0, 0), vib, "vibrator%d", vib->minor);
164         if (IS_ERR(dev)) {
165                 retval = -EINVAL;
166                 goto err_ida_remove;
167         }
168         vib->dev = dev;
169
170         INIT_DELAYED_WORK(&vib->delayed_work, gb_vibrator_worker);
171
172         gb_pm_runtime_put_autosuspend(bundle);
173
174         return 0;
175
176 err_ida_remove:
177         ida_simple_remove(&minors, vib->minor);
178 err_connection_disable:
179         gb_connection_disable(connection);
180 err_connection_destroy:
181         gb_connection_destroy(connection);
182 err_free_vib:
183         kfree(vib);
184
185         return retval;
186 }
187
188 static void gb_vibrator_disconnect(struct gb_bundle *bundle)
189 {
190         struct gb_vibrator_device *vib = greybus_get_drvdata(bundle);
191         int ret;
192
193         ret = gb_pm_runtime_get_sync(bundle);
194         if (ret)
195                 gb_pm_runtime_get_noresume(bundle);
196
197         if (cancel_delayed_work_sync(&vib->delayed_work))
198                 turn_off(vib);
199
200         device_unregister(vib->dev);
201         ida_simple_remove(&minors, vib->minor);
202         gb_connection_disable(vib->connection);
203         gb_connection_destroy(vib->connection);
204         kfree(vib);
205 }
206
207 static const struct greybus_bundle_id gb_vibrator_id_table[] = {
208         { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_VIBRATOR) },
209         { }
210 };
211 MODULE_DEVICE_TABLE(greybus, gb_vibrator_id_table);
212
213 static struct greybus_driver gb_vibrator_driver = {
214         .name           = "vibrator",
215         .probe          = gb_vibrator_probe,
216         .disconnect     = gb_vibrator_disconnect,
217         .id_table       = gb_vibrator_id_table,
218 };
219
220 static __init int gb_vibrator_init(void)
221 {
222         int retval;
223
224         retval = class_register(&vibrator_class);
225         if (retval)
226                 return retval;
227
228         retval = greybus_register(&gb_vibrator_driver);
229         if (retval)
230                 goto err_class_unregister;
231
232         return 0;
233
234 err_class_unregister:
235         class_unregister(&vibrator_class);
236
237         return retval;
238 }
239 module_init(gb_vibrator_init);
240
241 static __exit void gb_vibrator_exit(void)
242 {
243         greybus_deregister(&gb_vibrator_driver);
244         class_unregister(&vibrator_class);
245         ida_destroy(&minors);
246 }
247 module_exit(gb_vibrator_exit);
248
249 MODULE_LICENSE("GPL v2");