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