Source
// SPDX-License-Identifier: GPL-2.0
/*
* USB Role Switch Support
*
* Copyright (C) 2018 Intel Corporation
* Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
* Hans de Goede <hdegoede@redhat.com>
*/
static struct class *role_class;
struct usb_role_switch {
struct device dev;
struct mutex lock; /* device lock*/
enum usb_role role;
/* From descriptor */
struct device *usb2_port;
struct device *usb3_port;
struct device *udc;
usb_role_switch_set_t set;
usb_role_switch_get_t get;
bool allow_userspace_control;
};
/**
* usb_role_switch_set_role - Set USB role for a switch
* @sw: USB role switch
* @role: USB role to be switched to
*
* Set USB role @role for @sw.
*/
int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role)
{
int ret;
if (IS_ERR_OR_NULL(sw))
return 0;
mutex_lock(&sw->lock);
ret = sw->set(sw->dev.parent, role);
if (!ret)
sw->role = role;
mutex_unlock(&sw->lock);
return ret;
}
EXPORT_SYMBOL_GPL(usb_role_switch_set_role);
/**
* usb_role_switch_get_role - Get the USB role for a switch
* @sw: USB role switch
*
* Depending on the role-switch-driver this function returns either a cached
* value of the last set role, or reads back the actual value from the hardware.
*/
enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw)
{
enum usb_role role;
if (IS_ERR_OR_NULL(sw))
return USB_ROLE_NONE;
mutex_lock(&sw->lock);
if (sw->get)
role = sw->get(sw->dev.parent);
else
role = sw->role;
mutex_unlock(&sw->lock);
return role;
}
EXPORT_SYMBOL_GPL(usb_role_switch_get_role);
static int switch_fwnode_match(struct device *dev, const void *fwnode)
{
return dev_fwnode(dev) == fwnode;
}