mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 13:41:48 -04:00
usb: typec: Set the bus also for the port and plug altmodes
The port and plug altmodes can't be bound to the altmode drivers because the altmode drivers are meant for partner communication using the VDM (vendor defined messages), but they can still be part of the bus. The bus will make sure that the normal bus notifications are available also with the port altmodes. The previously used common device type for all alternate modes is replaced with separate dedicated device types for port, plug, and partner alternate modes. Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Signed-off-by: Chaoyi Chen <chaoyi.chen@rock-chips.com> Link: https://patch.msgid.link/20251208015500.94-2-kernel@airkyi.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
36723c6c1e
commit
67ab454262
@@ -445,7 +445,23 @@ static struct attribute *typec_attrs[] = {
|
||||
&dev_attr_description.attr,
|
||||
NULL
|
||||
};
|
||||
ATTRIBUTE_GROUPS(typec);
|
||||
|
||||
static umode_t typec_is_visible(struct kobject *kobj, struct attribute *attr, int n)
|
||||
{
|
||||
if (is_typec_partner_altmode(kobj_to_dev(kobj)))
|
||||
return attr->mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct attribute_group typec_group = {
|
||||
.is_visible = typec_is_visible,
|
||||
.attrs = typec_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *typec_groups[] = {
|
||||
&typec_group,
|
||||
NULL
|
||||
};
|
||||
|
||||
static int typec_match(struct device *dev, const struct device_driver *driver)
|
||||
{
|
||||
@@ -453,6 +469,9 @@ static int typec_match(struct device *dev, const struct device_driver *driver)
|
||||
struct typec_altmode *altmode = to_typec_altmode(dev);
|
||||
const struct typec_device_id *id;
|
||||
|
||||
if (!is_typec_partner_altmode(dev))
|
||||
return 0;
|
||||
|
||||
for (id = drv->id_table; id->svid; id++)
|
||||
if (id->svid == altmode->svid)
|
||||
return 1;
|
||||
@@ -463,6 +482,9 @@ static int typec_uevent(const struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
const struct typec_altmode *altmode = to_typec_altmode(dev);
|
||||
|
||||
if (!is_typec_partner_altmode(dev))
|
||||
return 0;
|
||||
|
||||
if (add_uevent_var(env, "SVID=%04X", altmode->svid))
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
@@ -29,8 +29,12 @@ struct altmode {
|
||||
#define to_altmode(d) container_of(d, struct altmode, adev)
|
||||
|
||||
extern const struct bus_type typec_bus;
|
||||
extern const struct device_type typec_altmode_dev_type;
|
||||
extern const struct device_type typec_port_altmode_dev_type;
|
||||
extern const struct device_type typec_plug_altmode_dev_type;
|
||||
extern const struct device_type typec_partner_altmode_dev_type;
|
||||
|
||||
#define is_typec_altmode(_dev_) (_dev_->type == &typec_altmode_dev_type)
|
||||
#define is_typec_port_altmode(dev) ((dev)->type == &typec_port_altmode_dev_type)
|
||||
#define is_typec_plug_altmode(dev) ((dev)->type == &typec_plug_altmode_dev_type)
|
||||
#define is_typec_partner_altmode(dev) ((dev)->type == &typec_partner_altmode_dev_type)
|
||||
|
||||
#endif /* __USB_TYPEC_ALTMODE_H__ */
|
||||
|
||||
@@ -235,7 +235,7 @@ static int altmode_match(struct device *dev, const void *data)
|
||||
struct typec_altmode *adev = to_typec_altmode(dev);
|
||||
const struct typec_device_id *id = data;
|
||||
|
||||
if (!is_typec_altmode(dev))
|
||||
if (!is_typec_port_altmode(dev))
|
||||
return 0;
|
||||
|
||||
return (adev->svid == id->svid);
|
||||
@@ -532,15 +532,28 @@ static void typec_altmode_release(struct device *dev)
|
||||
kfree(alt);
|
||||
}
|
||||
|
||||
const struct device_type typec_altmode_dev_type = {
|
||||
.name = "typec_alternate_mode",
|
||||
const struct device_type typec_port_altmode_dev_type = {
|
||||
.name = "typec_port_alternate_mode",
|
||||
.groups = typec_altmode_groups,
|
||||
.release = typec_altmode_release,
|
||||
};
|
||||
|
||||
const struct device_type typec_plug_altmode_dev_type = {
|
||||
.name = "typec_plug_alternate_mode",
|
||||
.groups = typec_altmode_groups,
|
||||
.release = typec_altmode_release,
|
||||
};
|
||||
|
||||
const struct device_type typec_partner_altmode_dev_type = {
|
||||
.name = "typec_partner_alternate_mode",
|
||||
.groups = typec_altmode_groups,
|
||||
.release = typec_altmode_release,
|
||||
};
|
||||
|
||||
static struct typec_altmode *
|
||||
typec_register_altmode(struct device *parent,
|
||||
const struct typec_altmode_desc *desc)
|
||||
const struct typec_altmode_desc *desc,
|
||||
const struct device_type *type)
|
||||
{
|
||||
unsigned int id = altmode_id_get(parent);
|
||||
bool is_port = is_typec_port(parent);
|
||||
@@ -575,7 +588,7 @@ typec_register_altmode(struct device *parent,
|
||||
|
||||
alt->adev.dev.parent = parent;
|
||||
alt->adev.dev.groups = alt->groups;
|
||||
alt->adev.dev.type = &typec_altmode_dev_type;
|
||||
alt->adev.dev.type = type;
|
||||
dev_set_name(&alt->adev.dev, "%s.%u", dev_name(parent), id);
|
||||
|
||||
get_device(alt->adev.dev.parent);
|
||||
@@ -584,9 +597,7 @@ typec_register_altmode(struct device *parent,
|
||||
if (!is_port)
|
||||
typec_altmode_set_partner(alt);
|
||||
|
||||
/* The partners are bind to drivers */
|
||||
if (is_typec_partner(parent))
|
||||
alt->adev.dev.bus = &typec_bus;
|
||||
alt->adev.dev.bus = &typec_bus;
|
||||
|
||||
/* Plug alt modes need a class to generate udev events. */
|
||||
if (is_typec_plug(parent))
|
||||
@@ -963,7 +974,7 @@ struct typec_altmode *
|
||||
typec_partner_register_altmode(struct typec_partner *partner,
|
||||
const struct typec_altmode_desc *desc)
|
||||
{
|
||||
return typec_register_altmode(&partner->dev, desc);
|
||||
return typec_register_altmode(&partner->dev, desc, &typec_partner_altmode_dev_type);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(typec_partner_register_altmode);
|
||||
|
||||
@@ -1193,7 +1204,7 @@ struct typec_altmode *
|
||||
typec_plug_register_altmode(struct typec_plug *plug,
|
||||
const struct typec_altmode_desc *desc)
|
||||
{
|
||||
return typec_register_altmode(&plug->dev, desc);
|
||||
return typec_register_altmode(&plug->dev, desc, &typec_plug_altmode_dev_type);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(typec_plug_register_altmode);
|
||||
|
||||
@@ -2493,7 +2504,7 @@ typec_port_register_altmode(struct typec_port *port,
|
||||
return ERR_CAST(retimer);
|
||||
}
|
||||
|
||||
adev = typec_register_altmode(&port->dev, desc);
|
||||
adev = typec_register_altmode(&port->dev, desc, &typec_port_altmode_dev_type);
|
||||
if (IS_ERR(adev)) {
|
||||
typec_retimer_put(retimer);
|
||||
typec_mux_put(mux);
|
||||
|
||||
Reference in New Issue
Block a user