staging: greybus: vibrator: remove KERNEL_VERSION checks
[linux-2.6-block.git] / drivers / staging / greybus / vibrator.c
CommitLineData
ac4029fb 1/*
4efe6065 2 * Greybus Vibrator protocol driver.
ac4029fb
GKH
3 *
4 * Copyright 2014 Google Inc.
a46e9671 5 * Copyright 2014 Linaro Ltd.
ac4029fb
GKH
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>
396671b1 15#include <linux/idr.h>
633e45ea
AC
16#include <linux/pm_runtime.h>
17
ac4029fb
GKH
18#include "greybus.h"
19
20struct gb_vibrator_device {
21 struct gb_connection *connection;
22 struct device *dev;
396671b1 23 int minor; /* vibrator minor number */
0900845a 24 struct delayed_work delayed_work;
ac4029fb
GKH
25};
26
6d653370 27/* Greybus Vibrator operation types */
ac4029fb
GKH
28#define GB_VIBRATOR_TYPE_ON 0x02
29#define GB_VIBRATOR_TYPE_OFF 0x03
ac4029fb 30
0900845a 31static int turn_off(struct gb_vibrator_device *vib)
ac4029fb 32{
633e45ea
AC
33 struct gb_bundle *bundle = vib->connection->bundle;
34 int ret;
35
0900845a
AC
36 ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_OFF,
37 NULL, 0, NULL, 0);
633e45ea
AC
38
39 gb_pm_runtime_put_autosuspend(bundle);
40
41 return ret;
ac4029fb
GKH
42}
43
0900845a 44static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms)
ac4029fb 45{
633e45ea
AC
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
0900845a
AC
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,
633e45ea 58 NULL, 0, NULL, 0);
0900845a
AC
59 if (ret) {
60 gb_pm_runtime_put_autosuspend(bundle);
61 return ret;
62 }
633e45ea 63
0900845a 64 schedule_delayed_work(&vib->delayed_work, msecs_to_jiffies(timeout_ms));
633e45ea 65
0900845a
AC
66 return 0;
67}
68
69static 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);
ac4029fb
GKH
76}
77
78static 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
ac4029fb
GKH
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}
100static DEVICE_ATTR_WO(timeout);
101
102static struct attribute *vibrator_attrs[] = {
103 &dev_attr_timeout.attr,
104 NULL,
105};
106ATTRIBUTE_GROUPS(vibrator);
107
108static struct class vibrator_class = {
109 .name = "vibrator",
110 .owner = THIS_MODULE,
ac4029fb 111 .dev_groups = vibrator_groups,
ac4029fb
GKH
112};
113
6b17492e 114static DEFINE_IDA(minors);
ac4029fb 115
e0deb079
JH
116static int gb_vibrator_probe(struct gb_bundle *bundle,
117 const struct greybus_bundle_id *id)
ac4029fb 118{
e0deb079
JH
119 struct greybus_descriptor_cport *cport_desc;
120 struct gb_connection *connection;
ac4029fb
GKH
121 struct gb_vibrator_device *vib;
122 struct device *dev;
123 int retval;
124
e0deb079
JH
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
ac4029fb
GKH
132 vib = kzalloc(sizeof(*vib), GFP_KERNEL);
133 if (!vib)
134 return -ENOMEM;
135
e0deb079
JH
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 }
0ec30632 142 gb_connection_set_data(connection, vib);
ac4029fb 143
e0deb079
JH
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
ac4029fb 152 /*
396671b1
GKH
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
ac4029fb
GKH
155 * can't find it at the moment...
156 */
6b17492e 157 vib->minor = ida_simple_get(&minors, 0, 0, GFP_KERNEL);
396671b1
GKH
158 if (vib->minor < 0) {
159 retval = vib->minor;
e0deb079 160 goto err_connection_disable;
396671b1 161 }
e0deb079 162 dev = device_create(&vibrator_class, &bundle->dev,
5ae2f55b 163 MKDEV(0, 0), vib, "vibrator%d", vib->minor);
ac4029fb
GKH
164 if (IS_ERR(dev)) {
165 retval = -EINVAL;
6b17492e 166 goto err_ida_remove;
ac4029fb 167 }
ac4029fb
GKH
168 vib->dev = dev;
169
0900845a
AC
170 INIT_DELAYED_WORK(&vib->delayed_work, gb_vibrator_worker);
171
633e45ea
AC
172 gb_pm_runtime_put_autosuspend(bundle);
173
ac4029fb
GKH
174 return 0;
175
6b17492e
GKH
176err_ida_remove:
177 ida_simple_remove(&minors, vib->minor);
e0deb079
JH
178err_connection_disable:
179 gb_connection_disable(connection);
180err_connection_destroy:
181 gb_connection_destroy(connection);
182err_free_vib:
ac4029fb 183 kfree(vib);
e0deb079 184
ac4029fb
GKH
185 return retval;
186}
187
e0deb079 188static void gb_vibrator_disconnect(struct gb_bundle *bundle)
ac4029fb 189{
e0deb079 190 struct gb_vibrator_device *vib = greybus_get_drvdata(bundle);
633e45ea
AC
191 int ret;
192
193 ret = gb_pm_runtime_get_sync(bundle);
194 if (ret)
195 gb_pm_runtime_get_noresume(bundle);
ac4029fb 196
0900845a
AC
197 if (cancel_delayed_work_sync(&vib->delayed_work))
198 turn_off(vib);
199
ac4029fb 200 device_unregister(vib->dev);
d7849bff 201 ida_simple_remove(&minors, vib->minor);
e0deb079
JH
202 gb_connection_disable(vib->connection);
203 gb_connection_destroy(vib->connection);
ac4029fb
GKH
204 kfree(vib);
205}
206
e0deb079
JH
207static const struct greybus_bundle_id gb_vibrator_id_table[] = {
208 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_VIBRATOR) },
209 { }
210};
211MODULE_DEVICE_TABLE(greybus, gb_vibrator_id_table);
212
213static 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,
ac4029fb
GKH
218};
219
e0deb079 220static __init int gb_vibrator_init(void)
ac4029fb
GKH
221{
222 int retval;
223
224 retval = class_register(&vibrator_class);
225 if (retval)
226 return retval;
227
e0deb079 228 retval = greybus_register(&gb_vibrator_driver);
d4efa688
JH
229 if (retval)
230 goto err_class_unregister;
231
232 return 0;
233
234err_class_unregister:
235 class_unregister(&vibrator_class);
236
237 return retval;
ac4029fb 238}
e0deb079 239module_init(gb_vibrator_init);
ac4029fb 240
e0deb079 241static __exit void gb_vibrator_exit(void)
ac4029fb 242{
e0deb079 243 greybus_deregister(&gb_vibrator_driver);
ac4029fb 244 class_unregister(&vibrator_class);
5c1ac694 245 ida_destroy(&minors);
ac4029fb 246}
e0deb079 247module_exit(gb_vibrator_exit);
66b676fd
GKH
248
249MODULE_LICENSE("GPL v2");