diff mbox series

[v2,3/7] usb: typec: Auto enter control for alternate modes

Message ID 20241030142833.v2.3.I439cffc7bf76d94f5850eb85980f1197c4f9154c@changeid
State New
Headers show
Series [v2,1/7] usb: typec: Add driver for Thunderbolt 3 Alternate Mode | expand

Commit Message

Abhishek Pandit-Subedi Oct. 30, 2024, 9:28 p.m. UTC
Add controls for whether an alternate mode is automatically entered when
a partner connects. The auto_enter control is only available on ports
and applies immediately after a partner connects. The default behavior
is to enable auto enter and drivers must explicitly disable it.

Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
---

(no changes since v1)

 Documentation/ABI/testing/sysfs-bus-typec |  9 +++++++
 drivers/usb/typec/altmodes/displayport.c  |  6 +++--
 drivers/usb/typec/altmodes/thunderbolt.c  |  3 ++-
 drivers/usb/typec/class.c                 | 31 +++++++++++++++++++++++
 include/linux/usb/typec.h                 |  2 ++
 include/linux/usb/typec_altmode.h         |  2 ++
 6 files changed, 50 insertions(+), 3 deletions(-)

Comments

Abhishek Pandit-Subedi Oct. 31, 2024, 10:48 p.m. UTC | #1
On Thu, Oct 31, 2024 at 7:33 AM Heikki Krogerus
<heikki.krogerus@linux.intel.com> wrote:
>
> On Wed, Oct 30, 2024 at 02:28:34PM -0700, Abhishek Pandit-Subedi wrote:
> > Add controls for whether an alternate mode is automatically entered when
> > a partner connects. The auto_enter control is only available on ports
> > and applies immediately after a partner connects. The default behavior
> > is to enable auto enter and drivers must explicitly disable it.
> >
> > Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
> > ---
> >
> > (no changes since v1)
> >
> >  Documentation/ABI/testing/sysfs-bus-typec |  9 +++++++
> >  drivers/usb/typec/altmodes/displayport.c  |  6 +++--
> >  drivers/usb/typec/altmodes/thunderbolt.c  |  3 ++-
> >  drivers/usb/typec/class.c                 | 31 +++++++++++++++++++++++
> >  include/linux/usb/typec.h                 |  2 ++
> >  include/linux/usb/typec_altmode.h         |  2 ++
> >  6 files changed, 50 insertions(+), 3 deletions(-)
> >
> > diff --git a/Documentation/ABI/testing/sysfs-bus-typec b/Documentation/ABI/testing/sysfs-bus-typec
> > index 205d9c91e2e1..f09d05727b82 100644
> > --- a/Documentation/ABI/testing/sysfs-bus-typec
> > +++ b/Documentation/ABI/testing/sysfs-bus-typec
> > @@ -12,6 +12,15 @@ Description:
> >
> >               Valid values are boolean.
> >
> > +What:                /sys/bus/typec/devices/.../auto_enter
> > +Date:                September 2024
> > +Contact:     Heikki Krogerus <heikki.krogerus@linux.intel.com>
> > +Description:
> > +             Controls whether a mode will be automatically entered when a partner is
> > +             connected.
> > +
> > +             This field is only valid and displayed on a port. Valid values are boolean.
>
> So, why can't this be controlled with the "active" property of the
> port altmode instead? That's why it's there.
>
> Sorry if I missed something in v1 related to this question.

There was a bit of discussion around this in another patch in v1:
https://patchwork.kernel.org/project/chrome-platform/patch/20240925092505.8.Ic14738918e3d026fa2d85e95fb68f8e07a0828d0@changeid/
And this patch is probably a good place to continue that discussion.

With the way altmodes drivers currently work, they will auto-enter
when probed. So if you have a partner that supports both displayport
and thunderbolt, they will both attempt to auto-enter on probe. I
think I could use the `active` field instead so that the port altmode
blocks entry until userspace enables it -- this would avoid the need
to add one more sysfs ABI. I'll actually go ahead and do this for the
next patch series I send up.

However, the underlying problem I'm trying to solve still exists: how
do you choose a specific altmode to enter if there are multiple to
choose from? I tried to implement a method that first tries USB4 and
then Thunderbolt and then DP but I realized that the altmode drivers
don't necessarily bind immediately after a partner altmode is
registered so I can't just call `activate` (since no ops are attached
to the partner altmode yet). Do you have any thoughts about how to
handle multiple modes as well as how to handle fallback mode entry
(i.e. thunderbolt fails so you try DPAM next)?

>
> thanks,
>
> --
> heikki
Heikki Krogerus Nov. 1, 2024, 1:59 p.m. UTC | #2
On Thu, Oct 31, 2024 at 03:48:45PM -0700, Abhishek Pandit-Subedi wrote:
> On Thu, Oct 31, 2024 at 7:33 AM Heikki Krogerus
> <heikki.krogerus@linux.intel.com> wrote:
> >
> > On Wed, Oct 30, 2024 at 02:28:34PM -0700, Abhishek Pandit-Subedi wrote:
> > > Add controls for whether an alternate mode is automatically entered when
> > > a partner connects. The auto_enter control is only available on ports
> > > and applies immediately after a partner connects. The default behavior
> > > is to enable auto enter and drivers must explicitly disable it.
> > >
> > > Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
> > > ---
> > >
> > > (no changes since v1)
> > >
> > >  Documentation/ABI/testing/sysfs-bus-typec |  9 +++++++
> > >  drivers/usb/typec/altmodes/displayport.c  |  6 +++--
> > >  drivers/usb/typec/altmodes/thunderbolt.c  |  3 ++-
> > >  drivers/usb/typec/class.c                 | 31 +++++++++++++++++++++++
> > >  include/linux/usb/typec.h                 |  2 ++
> > >  include/linux/usb/typec_altmode.h         |  2 ++
> > >  6 files changed, 50 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/Documentation/ABI/testing/sysfs-bus-typec b/Documentation/ABI/testing/sysfs-bus-typec
> > > index 205d9c91e2e1..f09d05727b82 100644
> > > --- a/Documentation/ABI/testing/sysfs-bus-typec
> > > +++ b/Documentation/ABI/testing/sysfs-bus-typec
> > > @@ -12,6 +12,15 @@ Description:
> > >
> > >               Valid values are boolean.
> > >
> > > +What:                /sys/bus/typec/devices/.../auto_enter
> > > +Date:                September 2024
> > > +Contact:     Heikki Krogerus <heikki.krogerus@linux.intel.com>
> > > +Description:
> > > +             Controls whether a mode will be automatically entered when a partner is
> > > +             connected.
> > > +
> > > +             This field is only valid and displayed on a port. Valid values are boolean.
> >
> > So, why can't this be controlled with the "active" property of the
> > port altmode instead? That's why it's there.
> >
> > Sorry if I missed something in v1 related to this question.
> 
> There was a bit of discussion around this in another patch in v1:
> https://patchwork.kernel.org/project/chrome-platform/patch/20240925092505.8.Ic14738918e3d026fa2d85e95fb68f8e07a0828d0@changeid/
> And this patch is probably a good place to continue that discussion.
> 
> With the way altmodes drivers currently work, they will auto-enter
> when probed. So if you have a partner that supports both displayport
> and thunderbolt, they will both attempt to auto-enter on probe. I
> think I could use the `active` field instead so that the port altmode
> blocks entry until userspace enables it -- this would avoid the need
> to add one more sysfs ABI. I'll actually go ahead and do this for the
> next patch series I send up.
> 
> However, the underlying problem I'm trying to solve still exists: how
> do you choose a specific altmode to enter if there are multiple to
> choose from? I tried to implement a method that first tries USB4 and
> then Thunderbolt and then DP but I realized that the altmode drivers
> don't necessarily bind immediately after a partner altmode is
> registered so I can't just call `activate` (since no ops are attached
> to the partner altmode yet). Do you have any thoughts about how to
> handle multiple modes as well as how to handle fallback mode entry
> (i.e. thunderbolt fails so you try DPAM next)?

If the user space needs to take over control of the entry order, then
can't it just de-activate all port alt modes by default, and then
activate the one that needs to enter? The port driver probable needs
to implent the "activate" callback for this.

The user space can see when the driver is bound to a device by
monitoring the uevents, no?

thanks,
Abhishek Pandit-Subedi Nov. 1, 2024, 4:53 p.m. UTC | #3
On Fri, Nov 1, 2024 at 6:59 AM Heikki Krogerus
<heikki.krogerus@linux.intel.com> wrote:
>
> On Thu, Oct 31, 2024 at 03:48:45PM -0700, Abhishek Pandit-Subedi wrote:
> > On Thu, Oct 31, 2024 at 7:33 AM Heikki Krogerus
> > <heikki.krogerus@linux.intel.com> wrote:
> > >
> > > On Wed, Oct 30, 2024 at 02:28:34PM -0700, Abhishek Pandit-Subedi wrote:
> > > > Add controls for whether an alternate mode is automatically entered when
> > > > a partner connects. The auto_enter control is only available on ports
> > > > and applies immediately after a partner connects. The default behavior
> > > > is to enable auto enter and drivers must explicitly disable it.
> > > >
> > > > Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
> > > > ---
> > > >
> > > > (no changes since v1)
> > > >
> > > >  Documentation/ABI/testing/sysfs-bus-typec |  9 +++++++
> > > >  drivers/usb/typec/altmodes/displayport.c  |  6 +++--
> > > >  drivers/usb/typec/altmodes/thunderbolt.c  |  3 ++-
> > > >  drivers/usb/typec/class.c                 | 31 +++++++++++++++++++++++
> > > >  include/linux/usb/typec.h                 |  2 ++
> > > >  include/linux/usb/typec_altmode.h         |  2 ++
> > > >  6 files changed, 50 insertions(+), 3 deletions(-)
> > > >
> > > > diff --git a/Documentation/ABI/testing/sysfs-bus-typec b/Documentation/ABI/testing/sysfs-bus-typec
> > > > index 205d9c91e2e1..f09d05727b82 100644
> > > > --- a/Documentation/ABI/testing/sysfs-bus-typec
> > > > +++ b/Documentation/ABI/testing/sysfs-bus-typec
> > > > @@ -12,6 +12,15 @@ Description:
> > > >
> > > >               Valid values are boolean.
> > > >
> > > > +What:                /sys/bus/typec/devices/.../auto_enter
> > > > +Date:                September 2024
> > > > +Contact:     Heikki Krogerus <heikki.krogerus@linux.intel.com>
> > > > +Description:
> > > > +             Controls whether a mode will be automatically entered when a partner is
> > > > +             connected.
> > > > +
> > > > +             This field is only valid and displayed on a port. Valid values are boolean.
> > >
> > > So, why can't this be controlled with the "active" property of the
> > > port altmode instead? That's why it's there.
> > >
> > > Sorry if I missed something in v1 related to this question.
> >
> > There was a bit of discussion around this in another patch in v1:
> > https://patchwork.kernel.org/project/chrome-platform/patch/20240925092505.8.Ic14738918e3d026fa2d85e95fb68f8e07a0828d0@changeid/
> > And this patch is probably a good place to continue that discussion.
> >
> > With the way altmodes drivers currently work, they will auto-enter
> > when probed. So if you have a partner that supports both displayport
> > and thunderbolt, they will both attempt to auto-enter on probe. I
> > think I could use the `active` field instead so that the port altmode
> > blocks entry until userspace enables it -- this would avoid the need
> > to add one more sysfs ABI. I'll actually go ahead and do this for the
> > next patch series I send up.
> >
> > However, the underlying problem I'm trying to solve still exists: how
> > do you choose a specific altmode to enter if there are multiple to
> > choose from? I tried to implement a method that first tries USB4 and
> > then Thunderbolt and then DP but I realized that the altmode drivers
> > don't necessarily bind immediately after a partner altmode is
> > registered so I can't just call `activate` (since no ops are attached
> > to the partner altmode yet). Do you have any thoughts about how to
> > handle multiple modes as well as how to handle fallback mode entry
> > (i.e. thunderbolt fails so you try DPAM next)?
>
> If the user space needs to take over control of the entry order, then
> can't it just de-activate all port alt modes by default, and then
> activate the one that needs to enter? The port driver probable needs
> to implent the "activate" callback for this.
>
> The user space can see when the driver is bound to a device by
> monitoring the uevents, no?

This requires userspace intervention to do the correct thing. Let's
take a real world example:

I have a TBT4 dock that supports DPAM (svid 0xff01), TBT (svid 0x8087)
and also USB4.

* When I plug in the dock, it enumerates and registers the partner
altmodes. The altmode bus matches typec_displayport and
typec_thunderbolt and loads the drivers for them. By default, both
drivers will try to activate their altmode on probe(). Having a
userspace daemon disable the altmode on the ports and enable them on
connection will probably work here.
* If I boot with the dock connected, the same thing happens but my
userspace daemon may not be running yet. What should the default
kernel behavior be to enter alt-modes then? When you throw USB4 into
the mix, this becomes another can of worms since you probably don't
want to downgrade from USB4 to DPAM.

On ChromeOS, prior to this patch series, our userspace daemon (typecd)
could handle all of this in userspace since it could just wait for
`num_alt_modes` to be filled on partner-attach before trying to enter
the right mode (via a side-band channel to the EC). After this change,
typecd will be in a similar bind -- it will have to wait until all
attached partner SVIDs have drivers attached (if available).

Underlying all this, I guess the real need here is for some sort of
signal that says: All partner modes are registered, any necessary
drivers for these modes are bound and you are ready to make a decision
on which mode to enter. Then, we could iteratively try to enter the
best mode (USB4 > TBT > DP) and report failure conditions on why it
couldn't be entered (i.e. Cable speed, partner problem / link
training, etc). This could be done in kernel or userspace depending on
the system.

>
> thanks,
>
> --
> heikki
Heikki Krogerus Nov. 4, 2024, 2:14 p.m. UTC | #4
On Fri, Nov 01, 2024 at 09:53:14AM -0700, Abhishek Pandit-Subedi wrote:
> On Fri, Nov 1, 2024 at 6:59 AM Heikki Krogerus
> <heikki.krogerus@linux.intel.com> wrote:
> >
> > On Thu, Oct 31, 2024 at 03:48:45PM -0700, Abhishek Pandit-Subedi wrote:
> > > On Thu, Oct 31, 2024 at 7:33 AM Heikki Krogerus
> > > <heikki.krogerus@linux.intel.com> wrote:
> > > >
> > > > On Wed, Oct 30, 2024 at 02:28:34PM -0700, Abhishek Pandit-Subedi wrote:
> > > > > Add controls for whether an alternate mode is automatically entered when
> > > > > a partner connects. The auto_enter control is only available on ports
> > > > > and applies immediately after a partner connects. The default behavior
> > > > > is to enable auto enter and drivers must explicitly disable it.
> > > > >
> > > > > Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
> > > > > ---
> > > > >
> > > > > (no changes since v1)
> > > > >
> > > > >  Documentation/ABI/testing/sysfs-bus-typec |  9 +++++++
> > > > >  drivers/usb/typec/altmodes/displayport.c  |  6 +++--
> > > > >  drivers/usb/typec/altmodes/thunderbolt.c  |  3 ++-
> > > > >  drivers/usb/typec/class.c                 | 31 +++++++++++++++++++++++
> > > > >  include/linux/usb/typec.h                 |  2 ++
> > > > >  include/linux/usb/typec_altmode.h         |  2 ++
> > > > >  6 files changed, 50 insertions(+), 3 deletions(-)
> > > > >
> > > > > diff --git a/Documentation/ABI/testing/sysfs-bus-typec b/Documentation/ABI/testing/sysfs-bus-typec
> > > > > index 205d9c91e2e1..f09d05727b82 100644
> > > > > --- a/Documentation/ABI/testing/sysfs-bus-typec
> > > > > +++ b/Documentation/ABI/testing/sysfs-bus-typec
> > > > > @@ -12,6 +12,15 @@ Description:
> > > > >
> > > > >               Valid values are boolean.
> > > > >
> > > > > +What:                /sys/bus/typec/devices/.../auto_enter
> > > > > +Date:                September 2024
> > > > > +Contact:     Heikki Krogerus <heikki.krogerus@linux.intel.com>
> > > > > +Description:
> > > > > +             Controls whether a mode will be automatically entered when a partner is
> > > > > +             connected.
> > > > > +
> > > > > +             This field is only valid and displayed on a port. Valid values are boolean.
> > > >
> > > > So, why can't this be controlled with the "active" property of the
> > > > port altmode instead? That's why it's there.
> > > >
> > > > Sorry if I missed something in v1 related to this question.
> > >
> > > There was a bit of discussion around this in another patch in v1:
> > > https://patchwork.kernel.org/project/chrome-platform/patch/20240925092505.8.Ic14738918e3d026fa2d85e95fb68f8e07a0828d0@changeid/
> > > And this patch is probably a good place to continue that discussion.
> > >
> > > With the way altmodes drivers currently work, they will auto-enter
> > > when probed. So if you have a partner that supports both displayport
> > > and thunderbolt, they will both attempt to auto-enter on probe. I
> > > think I could use the `active` field instead so that the port altmode
> > > blocks entry until userspace enables it -- this would avoid the need
> > > to add one more sysfs ABI. I'll actually go ahead and do this for the
> > > next patch series I send up.
> > >
> > > However, the underlying problem I'm trying to solve still exists: how
> > > do you choose a specific altmode to enter if there are multiple to
> > > choose from? I tried to implement a method that first tries USB4 and
> > > then Thunderbolt and then DP but I realized that the altmode drivers
> > > don't necessarily bind immediately after a partner altmode is
> > > registered so I can't just call `activate` (since no ops are attached
> > > to the partner altmode yet). Do you have any thoughts about how to
> > > handle multiple modes as well as how to handle fallback mode entry
> > > (i.e. thunderbolt fails so you try DPAM next)?
> >
> > If the user space needs to take over control of the entry order, then
> > can't it just de-activate all port alt modes by default, and then
> > activate the one that needs to enter? The port driver probable needs
> > to implent the "activate" callback for this.
> >
> > The user space can see when the driver is bound to a device by
> > monitoring the uevents, no?
> 
> This requires userspace intervention to do the correct thing. Let's
> take a real world example:
> 
> I have a TBT4 dock that supports DPAM (svid 0xff01), TBT (svid 0x8087)
> and also USB4.
> 
> * When I plug in the dock, it enumerates and registers the partner
> altmodes. The altmode bus matches typec_displayport and
> typec_thunderbolt and loads the drivers for them. By default, both
> drivers will try to activate their altmode on probe(). Having a
> userspace daemon disable the altmode on the ports and enable them on
> connection will probably work here.
> * If I boot with the dock connected, the same thing happens but my
> userspace daemon may not be running yet. What should the default
> kernel behavior be to enter alt-modes then? When you throw USB4 into
> the mix, this becomes another can of worms since you probably don't
> want to downgrade from USB4 to DPAM.

If you have already entered USB4, then all alt modes need fail to
enter with -EBUSY, just like when another alt mode was already
entered successfully. Right now the port driver is responsible of
checking USB4 status, but we can easily add a check for the usb_mode
of the partner to the typec_altmode_enter().

The default entry order will in practice be the order in which the
modes are discovered (so USB4 will always be first), but the port
drivers can of course influence this by registering the modes in a
specific order - first-come, first-served. But that is only useful if
the port driver knows the priorities of the modes.

You can leave the decision to the user space for example by adding
that "no_auto_enter", that's not a problem, but it still does not
require a new sysfs attribute file. You just use that flag to set the
default value for the "active" attribute.

> On ChromeOS, prior to this patch series, our userspace daemon (typecd)
> could handle all of this in userspace since it could just wait for
> `num_alt_modes` to be filled on partner-attach before trying to enter
> the right mode (via a side-band channel to the EC). After this change,
> typecd will be in a similar bind -- it will have to wait until all
> attached partner SVIDs have drivers attached (if available).
> 
> Underlying all this, I guess the real need here is for some sort of
> signal that says: All partner modes are registered, any necessary
> drivers for these modes are bound and you are ready to make a decision
> on which mode to enter. Then, we could iteratively try to enter the
> best mode (USB4 > TBT > DP) and report failure conditions on why it
> couldn't be entered (i.e. Cable speed, partner problem / link
> training, etc). This could be done in kernel or userspace depending on
> the system.

In user space you use the "num_alt_modes" to see how many alt modes
there are, and then simply wait for all of them (or just the ones that
you are interested in) get registered and bind to a driver. After that
you can enter which ever you want. I don't think you need anything
else there.

If you still need some way to tell the port drivers how to prioritise
the modes without user space, then I think you need some way for the
firmware to be able to deliver that information to the driver.

thanks,
diff mbox series

Patch

diff --git a/Documentation/ABI/testing/sysfs-bus-typec b/Documentation/ABI/testing/sysfs-bus-typec
index 205d9c91e2e1..f09d05727b82 100644
--- a/Documentation/ABI/testing/sysfs-bus-typec
+++ b/Documentation/ABI/testing/sysfs-bus-typec
@@ -12,6 +12,15 @@  Description:
 
 		Valid values are boolean.
 
+What:		/sys/bus/typec/devices/.../auto_enter
+Date:		September 2024
+Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description:
+		Controls whether a mode will be automatically entered when a partner is
+		connected.
+
+		This field is only valid and displayed on a port. Valid values are boolean.
+
 What:		/sys/bus/typec/devices/.../description
 Date:		July 2018
 Contact:	Heikki Krogerus <heikki.krogerus@linux.intel.com>
diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
index 2f03190a9873..62263f1d3a72 100644
--- a/drivers/usb/typec/altmodes/displayport.c
+++ b/drivers/usb/typec/altmodes/displayport.c
@@ -767,8 +767,10 @@  int dp_altmode_probe(struct typec_altmode *alt)
 	if (plug)
 		typec_altmode_set_drvdata(plug, dp);
 
-	dp->state = plug ? DP_STATE_ENTER_PRIME : DP_STATE_ENTER;
-	schedule_work(&dp->work);
+	if (port->auto_enter) {
+		dp->state = plug ? DP_STATE_ENTER_PRIME : DP_STATE_ENTER;
+		schedule_work(&dp->work);
+	}
 
 	return 0;
 }
diff --git a/drivers/usb/typec/altmodes/thunderbolt.c b/drivers/usb/typec/altmodes/thunderbolt.c
index 8380b22d26a7..181892bf1225 100644
--- a/drivers/usb/typec/altmodes/thunderbolt.c
+++ b/drivers/usb/typec/altmodes/thunderbolt.c
@@ -212,6 +212,7 @@  static const struct typec_altmode_ops tbt_altmode_ops = {
 
 static int tbt_altmode_probe(struct typec_altmode *alt)
 {
+	const struct typec_altmode *port = typec_altmode_get_partner(alt);
 	struct tbt_altmode *tbt;
 
 	tbt = devm_kzalloc(&alt->dev, sizeof(*tbt), GFP_KERNEL);
@@ -226,7 +227,7 @@  static int tbt_altmode_probe(struct typec_altmode *alt)
 	typec_altmode_set_drvdata(alt, tbt);
 	typec_altmode_set_ops(alt, &tbt_altmode_ops);
 
-	if (tbt_ready(alt)) {
+	if (port->auto_enter && tbt_ready(alt)) {
 		if (tbt->plug[TYPEC_PLUG_SOP_PP])
 			tbt->state = TBT_STATE_SOP_PP_ENTER;
 		else if (tbt->plug[TYPEC_PLUG_SOP_P])
diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
index 85494b9f7502..e74f835c6859 100644
--- a/drivers/usb/typec/class.c
+++ b/drivers/usb/typec/class.c
@@ -403,6 +403,31 @@  static ssize_t active_store(struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR_RW(active);
 
+static ssize_t
+auto_enter_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct typec_altmode *alt = to_typec_altmode(dev);
+
+	return sprintf(buf, "%s\n", alt->auto_enter ? "yes" : "no");
+}
+
+static ssize_t auto_enter_store(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t size)
+{
+	struct typec_altmode *adev = to_typec_altmode(dev);
+	bool auto_enter;
+	int ret;
+
+	ret = kstrtobool(buf, &auto_enter);
+	if (ret)
+		return ret;
+
+	adev->auto_enter = auto_enter;
+
+	return size;
+}
+static DEVICE_ATTR_RW(auto_enter);
+
 static ssize_t
 supported_roles_show(struct device *dev, struct device_attribute *attr,
 		     char *buf)
@@ -446,6 +471,7 @@  static DEVICE_ATTR_RO(svid);
 
 static struct attribute *typec_altmode_attrs[] = {
 	&dev_attr_active.attr,
+	&dev_attr_auto_enter.attr,
 	&dev_attr_mode.attr,
 	&dev_attr_svid.attr,
 	&dev_attr_vdo.attr,
@@ -461,6 +487,10 @@  static umode_t typec_altmode_attr_is_visible(struct kobject *kobj,
 		if (!adev->ops || !adev->ops->activate)
 			return 0444;
 
+	if (attr == &dev_attr_auto_enter.attr)
+		if (!is_typec_port(adev->dev.parent))
+			return 0;
+
 	return attr->mode;
 }
 
@@ -564,6 +594,7 @@  typec_register_altmode(struct device *parent,
 	if (is_port) {
 		alt->attrs[3] = &dev_attr_supported_roles.attr;
 		alt->adev.active = true; /* Enabled by default */
+		alt->adev.auto_enter = !desc->no_auto_enter;
 	}
 
 	sprintf(alt->group_name, "mode%d", desc->mode);
diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h
index d616b8807000..5336b7c92ca4 100644
--- a/include/linux/usb/typec.h
+++ b/include/linux/usb/typec.h
@@ -139,6 +139,7 @@  int typec_cable_set_identity(struct typec_cable *cable);
  * @svid: Standard or Vendor ID
  * @mode: Index of the Mode
  * @vdo: VDO returned by Discover Modes USB PD command
+ * @no_auto_enter: Only for ports. Disables auto enter which is default behavior.
  * @roles: Only for ports. DRP if the mode is available in both roles
  *
  * Description of an Alternate Mode which a connector, cable plug or partner
@@ -148,6 +149,7 @@  struct typec_altmode_desc {
 	u16			svid;
 	u8			mode;
 	u32			vdo;
+	bool			no_auto_enter;
 	/* Only used with ports */
 	enum typec_port_data	roles;
 };
diff --git a/include/linux/usb/typec_altmode.h b/include/linux/usb/typec_altmode.h
index b3c0866ea70f..ab7c3ebe4926 100644
--- a/include/linux/usb/typec_altmode.h
+++ b/include/linux/usb/typec_altmode.h
@@ -18,6 +18,7 @@  struct typec_altmode_ops;
  * @mode: Index of the Mode
  * @vdo: VDO returned by Discover Modes USB PD command
  * @active: Tells has the mode been entered or not
+ * @auto_enter: Tells whether to auto-enter mode (only valid for port mode).
  * @desc: Optional human readable description of the mode
  * @ops: Operations vector from the driver
  * @cable_ops: Cable operations vector from the driver.
@@ -28,6 +29,7 @@  struct typec_altmode {
 	int				mode;
 	u32				vdo;
 	unsigned int			active:1;
+	unsigned int			auto_enter:1;
 
 	char				*desc;
 	const struct typec_altmode_ops	*ops;