xref: /linux/drivers/usb/roles/class.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * USB Role Switch Support
4  *
5  * Copyright (C) 2018 Intel Corporation
6  * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
7  *         Hans de Goede <hdegoede@redhat.com>
8  */
9 
10 #include <linux/component.h>
11 #include <linux/usb/role.h>
12 #include <linux/property.h>
13 #include <linux/device.h>
14 #include <linux/lockdep.h>
15 #include <linux/module.h>
16 #include <linux/mutex.h>
17 #include <linux/slab.h>
18 
19 static const struct class role_class = {
20 	.name = "usb_role",
21 };
22 
23 struct usb_role_switch {
24 	struct device dev;
25 	struct lock_class_key key;
26 	struct mutex lock; /* device lock*/
27 	struct module *module; /* the module this device depends on */
28 	enum usb_role role;
29 	bool registered;
30 
31 	/* From descriptor */
32 	struct device *usb2_port;
33 	struct device *usb3_port;
34 	struct device *udc;
35 	usb_role_switch_set_t set;
36 	usb_role_switch_get_t get;
37 	bool allow_userspace_control;
38 };
39 
40 #define to_role_switch(d)	container_of(d, struct usb_role_switch, dev)
41 
connector_bind(struct device * dev,struct device * connector,void * data)42 static int connector_bind(struct device *dev, struct device *connector, void *data)
43 {
44 	int ret;
45 
46 	ret = sysfs_create_link(&dev->kobj, &connector->kobj, "connector");
47 	if (ret)
48 		return ret;
49 
50 	ret = sysfs_create_link(&connector->kobj, &dev->kobj, "usb-role-switch");
51 	if (ret)
52 		sysfs_remove_link(&dev->kobj, "connector");
53 
54 	return ret;
55 }
56 
connector_unbind(struct device * dev,struct device * connector,void * data)57 static void connector_unbind(struct device *dev, struct device *connector, void *data)
58 {
59 	sysfs_remove_link(&connector->kobj, "usb-role-switch");
60 	sysfs_remove_link(&dev->kobj, "connector");
61 }
62 
63 static const struct component_ops connector_ops = {
64 	.bind = connector_bind,
65 	.unbind = connector_unbind,
66 };
67 
68 /**
69  * usb_role_switch_set_role - Set USB role for a switch
70  * @sw: USB role switch
71  * @role: USB role to be switched to
72  *
73  * Set USB role @role for @sw.
74  */
usb_role_switch_set_role(struct usb_role_switch * sw,enum usb_role role)75 int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role)
76 {
77 	int ret;
78 
79 	if (IS_ERR_OR_NULL(sw))
80 		return 0;
81 
82 	if (!sw->registered)
83 		return -EOPNOTSUPP;
84 
85 	mutex_lock(&sw->lock);
86 
87 	ret = sw->set(sw, role);
88 	if (!ret) {
89 		sw->role = role;
90 		kobject_uevent(&sw->dev.kobj, KOBJ_CHANGE);
91 	}
92 
93 	mutex_unlock(&sw->lock);
94 
95 	return ret;
96 }
97 EXPORT_SYMBOL_GPL(usb_role_switch_set_role);
98 
99 /**
100  * usb_role_switch_get_role - Get the USB role for a switch
101  * @sw: USB role switch
102  *
103  * Depending on the role-switch-driver this function returns either a cached
104  * value of the last set role, or reads back the actual value from the hardware.
105  */
usb_role_switch_get_role(struct usb_role_switch * sw)106 enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw)
107 {
108 	enum usb_role role;
109 
110 	if (IS_ERR_OR_NULL(sw) || !sw->registered)
111 		return USB_ROLE_NONE;
112 
113 	mutex_lock(&sw->lock);
114 
115 	if (sw->get)
116 		role = sw->get(sw);
117 	else
118 		role = sw->role;
119 
120 	mutex_unlock(&sw->lock);
121 
122 	return role;
123 }
124 EXPORT_SYMBOL_GPL(usb_role_switch_get_role);
125 
usb_role_switch_match(const struct fwnode_handle * fwnode,const char * id,void * data)126 static void *usb_role_switch_match(const struct fwnode_handle *fwnode, const char *id,
127 				   void *data)
128 {
129 	struct device *dev;
130 
131 	if (id && !fwnode_property_present(fwnode, id))
132 		return NULL;
133 
134 	dev = class_find_device_by_fwnode(&role_class, fwnode);
135 
136 	return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER);
137 }
138 
139 static struct usb_role_switch *
usb_role_switch_is_parent(struct fwnode_handle * fwnode)140 usb_role_switch_is_parent(struct fwnode_handle *fwnode)
141 {
142 	struct fwnode_handle *parent = fwnode_get_parent(fwnode);
143 	struct device *dev;
144 
145 	if (!fwnode_property_present(parent, "usb-role-switch")) {
146 		fwnode_handle_put(parent);
147 		return NULL;
148 	}
149 
150 	dev = class_find_device_by_fwnode(&role_class, parent);
151 	fwnode_handle_put(parent);
152 	return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER);
153 }
154 
155 /**
156  * usb_role_switch_get - Find USB role switch linked with the caller
157  * @dev: The caller device
158  *
159  * Finds and returns role switch linked with @dev. The reference count for the
160  * found switch is incremented.
161  */
usb_role_switch_get(struct device * dev)162 struct usb_role_switch *usb_role_switch_get(struct device *dev)
163 {
164 	struct usb_role_switch *sw;
165 
166 	sw = usb_role_switch_is_parent(dev_fwnode(dev));
167 	if (!sw)
168 		sw = device_connection_find_match(dev, "usb-role-switch", NULL,
169 						  usb_role_switch_match);
170 
171 	if (!IS_ERR_OR_NULL(sw))
172 		WARN_ON(!try_module_get(sw->module));
173 
174 	return sw;
175 }
176 EXPORT_SYMBOL_GPL(usb_role_switch_get);
177 
178 /**
179  * fwnode_usb_role_switch_get - Find USB role switch linked with the caller
180  * @fwnode: The caller device node
181  *
182  * This is similar to the usb_role_switch_get() function above, but it searches
183  * the switch using fwnode instead of device entry.
184  */
fwnode_usb_role_switch_get(struct fwnode_handle * fwnode)185 struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *fwnode)
186 {
187 	struct usb_role_switch *sw;
188 
189 	sw = usb_role_switch_is_parent(fwnode);
190 	if (!sw)
191 		sw = fwnode_connection_find_match(fwnode, "usb-role-switch",
192 						  NULL, usb_role_switch_match);
193 	if (!IS_ERR_OR_NULL(sw))
194 		WARN_ON(!try_module_get(sw->module));
195 
196 	return sw;
197 }
198 EXPORT_SYMBOL_GPL(fwnode_usb_role_switch_get);
199 
200 /**
201  * usb_role_switch_put - Release handle to a switch
202  * @sw: USB Role Switch
203  *
204  * Decrement reference count for @sw.
205  */
usb_role_switch_put(struct usb_role_switch * sw)206 void usb_role_switch_put(struct usb_role_switch *sw)
207 {
208 	if (!IS_ERR_OR_NULL(sw)) {
209 		module_put(sw->module);
210 		put_device(&sw->dev);
211 	}
212 }
213 EXPORT_SYMBOL_GPL(usb_role_switch_put);
214 
215 /**
216  * usb_role_switch_find_by_fwnode - Find USB role switch with its fwnode
217  * @fwnode: fwnode of the USB Role Switch
218  *
219  * Finds and returns role switch with @fwnode. The reference count for the
220  * found switch is incremented.
221  */
222 struct usb_role_switch *
usb_role_switch_find_by_fwnode(const struct fwnode_handle * fwnode)223 usb_role_switch_find_by_fwnode(const struct fwnode_handle *fwnode)
224 {
225 	struct device *dev;
226 	struct usb_role_switch *sw = NULL;
227 
228 	if (!fwnode)
229 		return NULL;
230 
231 	dev = class_find_device_by_fwnode(&role_class, fwnode);
232 	if (dev) {
233 		sw = to_role_switch(dev);
234 		WARN_ON(!try_module_get(sw->module));
235 	}
236 
237 	return sw;
238 }
239 EXPORT_SYMBOL_GPL(usb_role_switch_find_by_fwnode);
240 
241 static umode_t
usb_role_switch_is_visible(struct kobject * kobj,struct attribute * attr,int n)242 usb_role_switch_is_visible(struct kobject *kobj, struct attribute *attr, int n)
243 {
244 	struct device *dev = kobj_to_dev(kobj);
245 	struct usb_role_switch *sw = to_role_switch(dev);
246 
247 	if (sw->allow_userspace_control)
248 		return attr->mode;
249 
250 	return 0;
251 }
252 
253 static const char * const usb_roles[] = {
254 	[USB_ROLE_NONE]		= "none",
255 	[USB_ROLE_HOST]		= "host",
256 	[USB_ROLE_DEVICE]	= "device",
257 };
258 
usb_role_string(enum usb_role role)259 const char *usb_role_string(enum usb_role role)
260 {
261 	if (role < 0 || role >= ARRAY_SIZE(usb_roles))
262 		return "unknown";
263 
264 	return usb_roles[role];
265 }
266 EXPORT_SYMBOL_GPL(usb_role_string);
267 
268 static ssize_t
role_show(struct device * dev,struct device_attribute * attr,char * buf)269 role_show(struct device *dev, struct device_attribute *attr, char *buf)
270 {
271 	struct usb_role_switch *sw = to_role_switch(dev);
272 	enum usb_role role = usb_role_switch_get_role(sw);
273 
274 	return sprintf(buf, "%s\n", usb_roles[role]);
275 }
276 
role_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)277 static ssize_t role_store(struct device *dev, struct device_attribute *attr,
278 			  const char *buf, size_t size)
279 {
280 	struct usb_role_switch *sw = to_role_switch(dev);
281 	int ret;
282 
283 	ret = sysfs_match_string(usb_roles, buf);
284 	if (ret < 0) {
285 		bool res;
286 
287 		/* Extra check if the user wants to disable the switch */
288 		ret = kstrtobool(buf, &res);
289 		if (ret || res)
290 			return -EINVAL;
291 	}
292 
293 	ret = usb_role_switch_set_role(sw, ret);
294 	if (ret)
295 		return ret;
296 
297 	return size;
298 }
299 static DEVICE_ATTR_RW(role);
300 
301 static struct attribute *usb_role_switch_attrs[] = {
302 	&dev_attr_role.attr,
303 	NULL,
304 };
305 
306 static const struct attribute_group usb_role_switch_group = {
307 	.is_visible = usb_role_switch_is_visible,
308 	.attrs = usb_role_switch_attrs,
309 };
310 
311 static const struct attribute_group *usb_role_switch_groups[] = {
312 	&usb_role_switch_group,
313 	NULL,
314 };
315 
usb_role_switch_uevent(const struct device * dev,struct kobj_uevent_env * env)316 static int usb_role_switch_uevent(const struct device *dev, struct kobj_uevent_env *env)
317 {
318 	int ret;
319 
320 	ret = add_uevent_var(env, "USB_ROLE_SWITCH=%s", dev_name(dev));
321 	if (ret)
322 		dev_err(dev, "failed to add uevent USB_ROLE_SWITCH\n");
323 
324 	return ret;
325 }
326 
usb_role_switch_release(struct device * dev)327 static void usb_role_switch_release(struct device *dev)
328 {
329 	struct usb_role_switch *sw = to_role_switch(dev);
330 
331 	mutex_destroy(&sw->lock);
332 	lockdep_unregister_key(&sw->key);
333 	kfree(sw);
334 }
335 
336 static const struct device_type usb_role_dev_type = {
337 	.name = "usb_role_switch",
338 	.groups = usb_role_switch_groups,
339 	.uevent = usb_role_switch_uevent,
340 	.release = usb_role_switch_release,
341 };
342 
343 /**
344  * usb_role_switch_register - Register USB Role Switch
345  * @parent: Parent device for the switch
346  * @desc: Description of the switch
347  *
348  * USB Role Switch is a device capable or choosing the role for USB connector.
349  * On platforms where the USB controller is dual-role capable, the controller
350  * driver will need to register the switch. On platforms where the USB host and
351  * USB device controllers behind the connector are separate, there will be a
352  * mux, and the driver for that mux will need to register the switch.
353  *
354  * Returns handle to a new role switch or ERR_PTR. The content of @desc is
355  * copied.
356  */
357 struct usb_role_switch *
usb_role_switch_register(struct device * parent,const struct usb_role_switch_desc * desc)358 usb_role_switch_register(struct device *parent,
359 			 const struct usb_role_switch_desc *desc)
360 {
361 	struct usb_role_switch *sw;
362 	int ret;
363 
364 	if (!desc || !desc->set)
365 		return ERR_PTR(-EINVAL);
366 
367 	sw = kzalloc(sizeof(*sw), GFP_KERNEL);
368 	if (!sw)
369 		return ERR_PTR(-ENOMEM);
370 
371 	lockdep_register_key(&sw->key);
372 	mutex_init_with_key(&sw->lock, &sw->key);
373 
374 	sw->allow_userspace_control = desc->allow_userspace_control;
375 	sw->usb2_port = desc->usb2_port;
376 	sw->usb3_port = desc->usb3_port;
377 	sw->udc = desc->udc;
378 	sw->set = desc->set;
379 	sw->get = desc->get;
380 
381 	sw->module = parent->driver->owner;
382 	sw->dev.parent = parent;
383 	sw->dev.fwnode = desc->fwnode;
384 	sw->dev.class = &role_class;
385 	sw->dev.type = &usb_role_dev_type;
386 	dev_set_drvdata(&sw->dev, desc->driver_data);
387 	dev_set_name(&sw->dev, "%s-role-switch",
388 		     desc->name ? desc->name : dev_name(parent));
389 
390 	ret = device_register(&sw->dev);
391 	if (ret) {
392 		put_device(&sw->dev);
393 		return ERR_PTR(ret);
394 	}
395 
396 	if (dev_fwnode(&sw->dev)) {
397 		ret = component_add(&sw->dev, &connector_ops);
398 		if (ret)
399 			dev_warn(&sw->dev, "failed to add component\n");
400 	}
401 
402 	sw->registered = true;
403 
404 	/* TODO: Symlinks for the host port and the device controller. */
405 
406 	return sw;
407 }
408 EXPORT_SYMBOL_GPL(usb_role_switch_register);
409 
410 /**
411  * usb_role_switch_unregister - Unregsiter USB Role Switch
412  * @sw: USB Role Switch
413  *
414  * Unregister switch that was registered with usb_role_switch_register().
415  */
usb_role_switch_unregister(struct usb_role_switch * sw)416 void usb_role_switch_unregister(struct usb_role_switch *sw)
417 {
418 	if (IS_ERR_OR_NULL(sw))
419 		return;
420 	sw->registered = false;
421 	if (dev_fwnode(&sw->dev))
422 		component_del(&sw->dev, &connector_ops);
423 	device_unregister(&sw->dev);
424 }
425 EXPORT_SYMBOL_GPL(usb_role_switch_unregister);
426 
427 /**
428  * usb_role_switch_set_drvdata - Assign private data pointer to a switch
429  * @sw: USB Role Switch
430  * @data: Private data pointer
431  */
usb_role_switch_set_drvdata(struct usb_role_switch * sw,void * data)432 void usb_role_switch_set_drvdata(struct usb_role_switch *sw, void *data)
433 {
434 	dev_set_drvdata(&sw->dev, data);
435 }
436 EXPORT_SYMBOL_GPL(usb_role_switch_set_drvdata);
437 
438 /**
439  * usb_role_switch_get_drvdata - Get the private data pointer of a switch
440  * @sw: USB Role Switch
441  */
usb_role_switch_get_drvdata(struct usb_role_switch * sw)442 void *usb_role_switch_get_drvdata(struct usb_role_switch *sw)
443 {
444 	return dev_get_drvdata(&sw->dev);
445 }
446 EXPORT_SYMBOL_GPL(usb_role_switch_get_drvdata);
447 
usb_roles_init(void)448 static int __init usb_roles_init(void)
449 {
450 	return class_register(&role_class);
451 }
452 subsys_initcall(usb_roles_init);
453 
usb_roles_exit(void)454 static void __exit usb_roles_exit(void)
455 {
456 	class_unregister(&role_class);
457 }
458 module_exit(usb_roles_exit);
459 
460 MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>");
461 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
462 MODULE_LICENSE("GPL v2");
463 MODULE_DESCRIPTION("USB Role Class");
464