Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * USB Role Switch Support
0004  *
0005  * Copyright (C) 2018 Intel Corporation
0006  * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
0007  *         Hans de Goede <hdegoede@redhat.com>
0008  */
0009 
0010 #include <linux/usb/role.h>
0011 #include <linux/property.h>
0012 #include <linux/device.h>
0013 #include <linux/module.h>
0014 #include <linux/mutex.h>
0015 #include <linux/slab.h>
0016 
0017 static struct class *role_class;
0018 
0019 struct usb_role_switch {
0020     struct device dev;
0021     struct mutex lock; /* device lock*/
0022     enum usb_role role;
0023 
0024     /* From descriptor */
0025     struct device *usb2_port;
0026     struct device *usb3_port;
0027     struct device *udc;
0028     usb_role_switch_set_t set;
0029     usb_role_switch_get_t get;
0030     bool allow_userspace_control;
0031 };
0032 
0033 #define to_role_switch(d)   container_of(d, struct usb_role_switch, dev)
0034 
0035 /**
0036  * usb_role_switch_set_role - Set USB role for a switch
0037  * @sw: USB role switch
0038  * @role: USB role to be switched to
0039  *
0040  * Set USB role @role for @sw.
0041  */
0042 int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role)
0043 {
0044     int ret;
0045 
0046     if (IS_ERR_OR_NULL(sw))
0047         return 0;
0048 
0049     mutex_lock(&sw->lock);
0050 
0051     ret = sw->set(sw, role);
0052     if (!ret) {
0053         sw->role = role;
0054         kobject_uevent(&sw->dev.kobj, KOBJ_CHANGE);
0055     }
0056 
0057     mutex_unlock(&sw->lock);
0058 
0059     return ret;
0060 }
0061 EXPORT_SYMBOL_GPL(usb_role_switch_set_role);
0062 
0063 /**
0064  * usb_role_switch_get_role - Get the USB role for a switch
0065  * @sw: USB role switch
0066  *
0067  * Depending on the role-switch-driver this function returns either a cached
0068  * value of the last set role, or reads back the actual value from the hardware.
0069  */
0070 enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw)
0071 {
0072     enum usb_role role;
0073 
0074     if (IS_ERR_OR_NULL(sw))
0075         return USB_ROLE_NONE;
0076 
0077     mutex_lock(&sw->lock);
0078 
0079     if (sw->get)
0080         role = sw->get(sw);
0081     else
0082         role = sw->role;
0083 
0084     mutex_unlock(&sw->lock);
0085 
0086     return role;
0087 }
0088 EXPORT_SYMBOL_GPL(usb_role_switch_get_role);
0089 
0090 static void *usb_role_switch_match(struct fwnode_handle *fwnode, const char *id,
0091                    void *data)
0092 {
0093     struct device *dev;
0094 
0095     if (id && !fwnode_property_present(fwnode, id))
0096         return NULL;
0097 
0098     dev = class_find_device_by_fwnode(role_class, fwnode);
0099 
0100     return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER);
0101 }
0102 
0103 static struct usb_role_switch *
0104 usb_role_switch_is_parent(struct fwnode_handle *fwnode)
0105 {
0106     struct fwnode_handle *parent = fwnode_get_parent(fwnode);
0107     struct device *dev;
0108 
0109     if (!parent || !fwnode_property_present(parent, "usb-role-switch"))
0110         return NULL;
0111 
0112     dev = class_find_device_by_fwnode(role_class, parent);
0113     return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER);
0114 }
0115 
0116 /**
0117  * usb_role_switch_get - Find USB role switch linked with the caller
0118  * @dev: The caller device
0119  *
0120  * Finds and returns role switch linked with @dev. The reference count for the
0121  * found switch is incremented.
0122  */
0123 struct usb_role_switch *usb_role_switch_get(struct device *dev)
0124 {
0125     struct usb_role_switch *sw;
0126 
0127     sw = usb_role_switch_is_parent(dev_fwnode(dev));
0128     if (!sw)
0129         sw = device_connection_find_match(dev, "usb-role-switch", NULL,
0130                           usb_role_switch_match);
0131 
0132     if (!IS_ERR_OR_NULL(sw))
0133         WARN_ON(!try_module_get(sw->dev.parent->driver->owner));
0134 
0135     return sw;
0136 }
0137 EXPORT_SYMBOL_GPL(usb_role_switch_get);
0138 
0139 /**
0140  * fwnode_usb_role_switch_get - Find USB role switch linked with the caller
0141  * @fwnode: The caller device node
0142  *
0143  * This is similar to the usb_role_switch_get() function above, but it searches
0144  * the switch using fwnode instead of device entry.
0145  */
0146 struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *fwnode)
0147 {
0148     struct usb_role_switch *sw;
0149 
0150     sw = usb_role_switch_is_parent(fwnode);
0151     if (!sw)
0152         sw = fwnode_connection_find_match(fwnode, "usb-role-switch",
0153                           NULL, usb_role_switch_match);
0154     if (!IS_ERR_OR_NULL(sw))
0155         WARN_ON(!try_module_get(sw->dev.parent->driver->owner));
0156 
0157     return sw;
0158 }
0159 EXPORT_SYMBOL_GPL(fwnode_usb_role_switch_get);
0160 
0161 /**
0162  * usb_role_switch_put - Release handle to a switch
0163  * @sw: USB Role Switch
0164  *
0165  * Decrement reference count for @sw.
0166  */
0167 void usb_role_switch_put(struct usb_role_switch *sw)
0168 {
0169     if (!IS_ERR_OR_NULL(sw)) {
0170         module_put(sw->dev.parent->driver->owner);
0171         put_device(&sw->dev);
0172     }
0173 }
0174 EXPORT_SYMBOL_GPL(usb_role_switch_put);
0175 
0176 /**
0177  * usb_role_switch_find_by_fwnode - Find USB role switch with its fwnode
0178  * @fwnode: fwnode of the USB Role Switch
0179  *
0180  * Finds and returns role switch with @fwnode. The reference count for the
0181  * found switch is incremented.
0182  */
0183 struct usb_role_switch *
0184 usb_role_switch_find_by_fwnode(const struct fwnode_handle *fwnode)
0185 {
0186     struct device *dev;
0187 
0188     if (!fwnode)
0189         return NULL;
0190 
0191     dev = class_find_device_by_fwnode(role_class, fwnode);
0192     if (dev)
0193         WARN_ON(!try_module_get(dev->parent->driver->owner));
0194 
0195     return dev ? to_role_switch(dev) : NULL;
0196 }
0197 EXPORT_SYMBOL_GPL(usb_role_switch_find_by_fwnode);
0198 
0199 static umode_t
0200 usb_role_switch_is_visible(struct kobject *kobj, struct attribute *attr, int n)
0201 {
0202     struct device *dev = kobj_to_dev(kobj);
0203     struct usb_role_switch *sw = to_role_switch(dev);
0204 
0205     if (sw->allow_userspace_control)
0206         return attr->mode;
0207 
0208     return 0;
0209 }
0210 
0211 static const char * const usb_roles[] = {
0212     [USB_ROLE_NONE]     = "none",
0213     [USB_ROLE_HOST]     = "host",
0214     [USB_ROLE_DEVICE]   = "device",
0215 };
0216 
0217 const char *usb_role_string(enum usb_role role)
0218 {
0219     if (role < 0 || role >= ARRAY_SIZE(usb_roles))
0220         return "unknown";
0221 
0222     return usb_roles[role];
0223 }
0224 EXPORT_SYMBOL_GPL(usb_role_string);
0225 
0226 static ssize_t
0227 role_show(struct device *dev, struct device_attribute *attr, char *buf)
0228 {
0229     struct usb_role_switch *sw = to_role_switch(dev);
0230     enum usb_role role = usb_role_switch_get_role(sw);
0231 
0232     return sprintf(buf, "%s\n", usb_roles[role]);
0233 }
0234 
0235 static ssize_t role_store(struct device *dev, struct device_attribute *attr,
0236               const char *buf, size_t size)
0237 {
0238     struct usb_role_switch *sw = to_role_switch(dev);
0239     int ret;
0240 
0241     ret = sysfs_match_string(usb_roles, buf);
0242     if (ret < 0) {
0243         bool res;
0244 
0245         /* Extra check if the user wants to disable the switch */
0246         ret = kstrtobool(buf, &res);
0247         if (ret || res)
0248             return -EINVAL;
0249     }
0250 
0251     ret = usb_role_switch_set_role(sw, ret);
0252     if (ret)
0253         return ret;
0254 
0255     return size;
0256 }
0257 static DEVICE_ATTR_RW(role);
0258 
0259 static struct attribute *usb_role_switch_attrs[] = {
0260     &dev_attr_role.attr,
0261     NULL,
0262 };
0263 
0264 static const struct attribute_group usb_role_switch_group = {
0265     .is_visible = usb_role_switch_is_visible,
0266     .attrs = usb_role_switch_attrs,
0267 };
0268 
0269 static const struct attribute_group *usb_role_switch_groups[] = {
0270     &usb_role_switch_group,
0271     NULL,
0272 };
0273 
0274 static int
0275 usb_role_switch_uevent(struct device *dev, struct kobj_uevent_env *env)
0276 {
0277     int ret;
0278 
0279     ret = add_uevent_var(env, "USB_ROLE_SWITCH=%s", dev_name(dev));
0280     if (ret)
0281         dev_err(dev, "failed to add uevent USB_ROLE_SWITCH\n");
0282 
0283     return ret;
0284 }
0285 
0286 static void usb_role_switch_release(struct device *dev)
0287 {
0288     struct usb_role_switch *sw = to_role_switch(dev);
0289 
0290     kfree(sw);
0291 }
0292 
0293 static const struct device_type usb_role_dev_type = {
0294     .name = "usb_role_switch",
0295     .groups = usb_role_switch_groups,
0296     .uevent = usb_role_switch_uevent,
0297     .release = usb_role_switch_release,
0298 };
0299 
0300 /**
0301  * usb_role_switch_register - Register USB Role Switch
0302  * @parent: Parent device for the switch
0303  * @desc: Description of the switch
0304  *
0305  * USB Role Switch is a device capable or choosing the role for USB connector.
0306  * On platforms where the USB controller is dual-role capable, the controller
0307  * driver will need to register the switch. On platforms where the USB host and
0308  * USB device controllers behind the connector are separate, there will be a
0309  * mux, and the driver for that mux will need to register the switch.
0310  *
0311  * Returns handle to a new role switch or ERR_PTR. The content of @desc is
0312  * copied.
0313  */
0314 struct usb_role_switch *
0315 usb_role_switch_register(struct device *parent,
0316              const struct usb_role_switch_desc *desc)
0317 {
0318     struct usb_role_switch *sw;
0319     int ret;
0320 
0321     if (!desc || !desc->set)
0322         return ERR_PTR(-EINVAL);
0323 
0324     sw = kzalloc(sizeof(*sw), GFP_KERNEL);
0325     if (!sw)
0326         return ERR_PTR(-ENOMEM);
0327 
0328     mutex_init(&sw->lock);
0329 
0330     sw->allow_userspace_control = desc->allow_userspace_control;
0331     sw->usb2_port = desc->usb2_port;
0332     sw->usb3_port = desc->usb3_port;
0333     sw->udc = desc->udc;
0334     sw->set = desc->set;
0335     sw->get = desc->get;
0336 
0337     sw->dev.parent = parent;
0338     sw->dev.fwnode = desc->fwnode;
0339     sw->dev.class = role_class;
0340     sw->dev.type = &usb_role_dev_type;
0341     dev_set_drvdata(&sw->dev, desc->driver_data);
0342     dev_set_name(&sw->dev, "%s-role-switch",
0343              desc->name ? desc->name : dev_name(parent));
0344 
0345     ret = device_register(&sw->dev);
0346     if (ret) {
0347         put_device(&sw->dev);
0348         return ERR_PTR(ret);
0349     }
0350 
0351     /* TODO: Symlinks for the host port and the device controller. */
0352 
0353     return sw;
0354 }
0355 EXPORT_SYMBOL_GPL(usb_role_switch_register);
0356 
0357 /**
0358  * usb_role_switch_unregister - Unregsiter USB Role Switch
0359  * @sw: USB Role Switch
0360  *
0361  * Unregister switch that was registered with usb_role_switch_register().
0362  */
0363 void usb_role_switch_unregister(struct usb_role_switch *sw)
0364 {
0365     if (!IS_ERR_OR_NULL(sw))
0366         device_unregister(&sw->dev);
0367 }
0368 EXPORT_SYMBOL_GPL(usb_role_switch_unregister);
0369 
0370 /**
0371  * usb_role_switch_set_drvdata - Assign private data pointer to a switch
0372  * @sw: USB Role Switch
0373  * @data: Private data pointer
0374  */
0375 void usb_role_switch_set_drvdata(struct usb_role_switch *sw, void *data)
0376 {
0377     dev_set_drvdata(&sw->dev, data);
0378 }
0379 EXPORT_SYMBOL_GPL(usb_role_switch_set_drvdata);
0380 
0381 /**
0382  * usb_role_switch_get_drvdata - Get the private data pointer of a switch
0383  * @sw: USB Role Switch
0384  */
0385 void *usb_role_switch_get_drvdata(struct usb_role_switch *sw)
0386 {
0387     return dev_get_drvdata(&sw->dev);
0388 }
0389 EXPORT_SYMBOL_GPL(usb_role_switch_get_drvdata);
0390 
0391 static int __init usb_roles_init(void)
0392 {
0393     role_class = class_create(THIS_MODULE, "usb_role");
0394     return PTR_ERR_OR_ZERO(role_class);
0395 }
0396 subsys_initcall(usb_roles_init);
0397 
0398 static void __exit usb_roles_exit(void)
0399 {
0400     class_destroy(role_class);
0401 }
0402 module_exit(usb_roles_exit);
0403 
0404 MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>");
0405 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
0406 MODULE_LICENSE("GPL v2");
0407 MODULE_DESCRIPTION("USB Role Class");