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 #include <linux/greybus.h>
17 
18 struct gb_vibrator_device {
19 	struct gb_connection	*connection;
20 	struct device		*dev;
21 	int			minor;		/* vibrator minor number */
22 	struct delayed_work     delayed_work;
23 };
24 
25 /* Greybus Vibrator operation types */
26 #define	GB_VIBRATOR_TYPE_ON			0x02
27 #define	GB_VIBRATOR_TYPE_OFF			0x03
28 
turn_off(struct gb_vibrator_device * vib)29 static int turn_off(struct gb_vibrator_device *vib)
30 {
31 	struct gb_bundle *bundle = vib->connection->bundle;
32 	int ret;
33 
34 	ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_OFF,
35 				NULL, 0, NULL, 0);
36 
37 	gb_pm_runtime_put_autosuspend(bundle);
38 
39 	return ret;
40 }
41 
turn_on(struct gb_vibrator_device * vib,u16 timeout_ms)42 static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms)
43 {
44 	struct gb_bundle *bundle = vib->connection->bundle;
45 	int ret;
46 
47 	ret = gb_pm_runtime_get_sync(bundle);
48 	if (ret)
49 		return ret;
50 
51 	/* Vibrator was switched ON earlier */
52 	if (cancel_delayed_work_sync(&vib->delayed_work))
53 		turn_off(vib);
54 
55 	ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_ON,
56 				NULL, 0, NULL, 0);
57 	if (ret) {
58 		gb_pm_runtime_put_autosuspend(bundle);
59 		return ret;
60 	}
61 
62 	schedule_delayed_work(&vib->delayed_work, msecs_to_jiffies(timeout_ms));
63 
64 	return 0;
65 }
66 
gb_vibrator_worker(struct work_struct * work)67 static void gb_vibrator_worker(struct work_struct *work)
68 {
69 	struct delayed_work *delayed_work = to_delayed_work(work);
70 	struct gb_vibrator_device *vib =
71 		container_of(delayed_work,
72 			     struct gb_vibrator_device,
73 			     delayed_work);
74 
75 	turn_off(vib);
76 }
77 
timeout_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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 	.dev_groups	= vibrator_groups,
111 };
112 
113 static DEFINE_IDA(minors);
114 
gb_vibrator_probe(struct gb_bundle * bundle,const struct greybus_bundle_id * id)115 static int gb_vibrator_probe(struct gb_bundle *bundle,
116 			     const struct greybus_bundle_id *id)
117 {
118 	struct greybus_descriptor_cport *cport_desc;
119 	struct gb_connection *connection;
120 	struct gb_vibrator_device *vib;
121 	struct device *dev;
122 	int retval;
123 
124 	if (bundle->num_cports != 1)
125 		return -ENODEV;
126 
127 	cport_desc = &bundle->cport_desc[0];
128 	if (cport_desc->protocol_id != GREYBUS_PROTOCOL_VIBRATOR)
129 		return -ENODEV;
130 
131 	vib = kzalloc(sizeof(*vib), GFP_KERNEL);
132 	if (!vib)
133 		return -ENOMEM;
134 
135 	connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id),
136 					  NULL);
137 	if (IS_ERR(connection)) {
138 		retval = PTR_ERR(connection);
139 		goto err_free_vib;
140 	}
141 	gb_connection_set_data(connection, vib);
142 
143 	vib->connection = connection;
144 
145 	greybus_set_drvdata(bundle, vib);
146 
147 	retval = gb_connection_enable(connection);
148 	if (retval)
149 		goto err_connection_destroy;
150 
151 	/*
152 	 * For now we create a device in sysfs for the vibrator, but odds are
153 	 * there is a "real" device somewhere in the kernel for this, but I
154 	 * can't find it at the moment...
155 	 */
156 	vib->minor = ida_simple_get(&minors, 0, 0, GFP_KERNEL);
157 	if (vib->minor < 0) {
158 		retval = vib->minor;
159 		goto err_connection_disable;
160 	}
161 	dev = device_create(&vibrator_class, &bundle->dev,
162 			    MKDEV(0, 0), vib, "vibrator%d", vib->minor);
163 	if (IS_ERR(dev)) {
164 		retval = -EINVAL;
165 		goto err_ida_remove;
166 	}
167 	vib->dev = dev;
168 
169 	INIT_DELAYED_WORK(&vib->delayed_work, gb_vibrator_worker);
170 
171 	gb_pm_runtime_put_autosuspend(bundle);
172 
173 	return 0;
174 
175 err_ida_remove:
176 	ida_simple_remove(&minors, vib->minor);
177 err_connection_disable:
178 	gb_connection_disable(connection);
179 err_connection_destroy:
180 	gb_connection_destroy(connection);
181 err_free_vib:
182 	kfree(vib);
183 
184 	return retval;
185 }
186 
gb_vibrator_disconnect(struct gb_bundle * bundle)187 static void gb_vibrator_disconnect(struct gb_bundle *bundle)
188 {
189 	struct gb_vibrator_device *vib = greybus_get_drvdata(bundle);
190 	int ret;
191 
192 	ret = gb_pm_runtime_get_sync(bundle);
193 	if (ret)
194 		gb_pm_runtime_get_noresume(bundle);
195 
196 	if (cancel_delayed_work_sync(&vib->delayed_work))
197 		turn_off(vib);
198 
199 	device_unregister(vib->dev);
200 	ida_simple_remove(&minors, vib->minor);
201 	gb_connection_disable(vib->connection);
202 	gb_connection_destroy(vib->connection);
203 	kfree(vib);
204 }
205 
206 static const struct greybus_bundle_id gb_vibrator_id_table[] = {
207 	{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_VIBRATOR) },
208 	{ }
209 };
210 MODULE_DEVICE_TABLE(greybus, gb_vibrator_id_table);
211 
212 static struct greybus_driver gb_vibrator_driver = {
213 	.name		= "vibrator",
214 	.probe		= gb_vibrator_probe,
215 	.disconnect	= gb_vibrator_disconnect,
216 	.id_table	= gb_vibrator_id_table,
217 };
218 
gb_vibrator_init(void)219 static __init int gb_vibrator_init(void)
220 {
221 	int retval;
222 
223 	retval = class_register(&vibrator_class);
224 	if (retval)
225 		return retval;
226 
227 	retval = greybus_register(&gb_vibrator_driver);
228 	if (retval)
229 		goto err_class_unregister;
230 
231 	return 0;
232 
233 err_class_unregister:
234 	class_unregister(&vibrator_class);
235 
236 	return retval;
237 }
238 module_init(gb_vibrator_init);
239 
gb_vibrator_exit(void)240 static __exit void gb_vibrator_exit(void)
241 {
242 	greybus_deregister(&gb_vibrator_driver);
243 	class_unregister(&vibrator_class);
244 	ida_destroy(&minors);
245 }
246 module_exit(gb_vibrator_exit);
247 
248 MODULE_LICENSE("GPL v2");
249