linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: Peter Rosin <peda@axentia.se>
To: Xu Yang <xu.yang_2@nxp.com>,
	heikki.krogerus@linux.intel.com, robh+dt@kernel.org,
	shawnguo@kernel.org
Cc: gregkh@linuxfoundation.org, linux@roeck-us.net, jun.li@nxp.com,
	linux-usb@vger.kernel.org, linux-imx@nxp.com,
	devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH 3/4] usb: typec: mux: add typec orientation switch support via mux controller
Date: Tue, 23 Aug 2022 08:13:06 +0200	[thread overview]
Message-ID: <c2261f2b-fa47-f988-bf5a-aaa3169c8c7e@axentia.se> (raw)
In-Reply-To: <20220822153517.3747679-4-xu.yang_2@nxp.com>

Hi!

2022-08-22 at 17:35, Xu Yang wrote:
> Some dedicated mux block can use existing mux controller as a mux
> provider, typec port as a consumer to select channel for orientation
> switch, this can be an alternate way to control typec orientation switch.
> Also, one mux controller could cover highspeed, superspeed and sideband
> use case one time in this implementation.
> 
> Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> ---
>  drivers/usb/typec/mux.c       | 74 +++++++++++++++++++++++++++++++++++
>  include/linux/usb/typec_mux.h |  7 +---
>  2 files changed, 76 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c
> index 464330776cd6..5ee960fb668d 100644
> --- a/drivers/usb/typec/mux.c
> +++ b/drivers/usb/typec/mux.c
> @@ -13,6 +13,7 @@
>  #include <linux/mutex.h>
>  #include <linux/property.h>
>  #include <linux/slab.h>
> +#include <linux/mux/consumer.h>
>  
>  #include "class.h"
>  #include "mux.h"
> @@ -22,6 +23,11 @@
>  struct typec_switch {
>  	struct typec_switch_dev *sw_devs[TYPEC_MUX_MAX_DEVS];
>  	unsigned int num_sw_devs;
> +
> +	/* Could handle HighSpeed, SuperSpeed, Sideband switch one time */
> +	struct mux_control *mux_switch;
> +	/* 3 state correspond to NONE, NORMAL, REVERSE for all switches */
> +	int mux_states[3];
>  };
>  
>  static int switch_fwnode_match(struct device *dev, const void *fwnode)
> @@ -117,6 +123,58 @@ struct typec_switch *fwnode_typec_switch_get(struct fwnode_handle *fwnode)
>  }
>  EXPORT_SYMBOL_GPL(fwnode_typec_switch_get);
>  
> +static struct typec_switch *mux_control_typec_switch_get(struct device *dev)
> +{
> +	struct typec_switch *sw;
> +	struct mux_control *mux;
> +	int ret;
> +
> +	if (!device_property_present(dev, "mux-controls"))
> +		return NULL;
> +
> +	sw = kzalloc(sizeof(*sw), GFP_KERNEL);
> +	if (!sw)
> +		return ERR_PTR(-ENOMEM);
> +
> +	mux = mux_control_get(dev, NULL);
> +	if (!IS_ERR(mux)) {
> +		sw->mux_switch = mux;
> +		ret = device_property_read_u32_array(dev,
> +			"typec-switch-states", sw->mux_states, 3);
> +		if (ret) {
> +			kfree(sw);
> +			return ERR_PTR(ret);
> +		}
> +	} else {
> +		kfree(sw);
> +		return ERR_CAST(mux);
> +	}
> +
> +	return sw;
> +}
> +
> +/**
> + * typec_switch_get - Find USB Type-C orientation switch
> + * @dev: The device using switch
> + *
> + * Finds a switch used by @dev. Returns a reference to the switch on
> + * success, NULL if no matching connection was found, or
> + * ERR_PTR(-EPROBE_DEFER) when a connection was found but the switch
> + * has not been enumerated yet, or ERR_PTR with a negative errno.
> + */
> +struct typec_switch *typec_switch_get(struct device *dev)
> +{
> +	struct typec_switch *sw;
> +
> +	sw = fwnode_typec_switch_get(dev_fwnode(dev));
> +	if (!sw)
> +		/* Try get switch based on mux control */
> +		sw = mux_control_typec_switch_get(dev);
> +
> +	return sw;
> +}
> +EXPORT_SYMBOL_GPL(typec_switch_get);
> +
>  /**
>   * typec_switch_put - Release USB Type-C orientation switch
>   * @sw: USB Type-C orientation switch
> @@ -137,6 +195,10 @@ void typec_switch_put(struct typec_switch *sw)
>  		module_put(sw_dev->dev.parent->driver->owner);
>  		put_device(&sw_dev->dev);
>  	}
> +
> +	if (sw->mux_switch)
> +		mux_control_put(sw->mux_switch);
> +
>  	kfree(sw);
>  }
>  EXPORT_SYMBOL_GPL(typec_switch_put);
> @@ -204,6 +266,7 @@ int typec_switch_set(struct typec_switch *sw,
>  		     enum typec_orientation orientation)
>  {
>  	struct typec_switch_dev *sw_dev;
> +	struct mux_control *mux;
>  	unsigned int i;
>  	int ret;
>  
> @@ -218,6 +281,17 @@ int typec_switch_set(struct typec_switch *sw,
>  			return ret;
>  	}
>  
> +	mux = sw->mux_switch;
> +	if (mux) {
> +		ret = mux_control_deselect(mux);

This is broken. Please read the documentation for mux_control_select and
mux_control_deselect. Every call to mux_control_deselect *must* be paired
with a *successful* call to mux_control_select. Here, mux_control_deselect
is called unconditionally (as long as a mux is configured).

Yes, agreed, that is indeed awkward (and fragile). But those are the rules.
(the mux interface was not designed for long-time selects like this)

Cheers,
Peter

> +		if (ret)
> +			return ret;
> +
> +		ret = mux_control_select(mux, sw->mux_states[orientation]);
> +		if (ret)
> +			return ret;
> +	}
> +
>  	return 0;
>  }
>  EXPORT_SYMBOL_GPL(typec_switch_set);
> diff --git a/include/linux/usb/typec_mux.h b/include/linux/usb/typec_mux.h
> index 9292f0e07846..2287e5a5f591 100644
> --- a/include/linux/usb/typec_mux.h
> +++ b/include/linux/usb/typec_mux.h
> @@ -24,16 +24,13 @@ struct typec_switch_desc {
>  	void *drvdata;
>  };
>  
> +
> +struct typec_switch *typec_switch_get(struct device *dev);
>  struct typec_switch *fwnode_typec_switch_get(struct fwnode_handle *fwnode);
>  void typec_switch_put(struct typec_switch *sw);
>  int typec_switch_set(struct typec_switch *sw,
>  		     enum typec_orientation orientation);
>  
> -static inline struct typec_switch *typec_switch_get(struct device *dev)
> -{
> -	return fwnode_typec_switch_get(dev_fwnode(dev));
> -}
> -
>  struct typec_switch_dev *
>  typec_switch_register(struct device *parent,
>  		      const struct typec_switch_desc *desc);

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  parent reply	other threads:[~2022-08-23  6:14 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-22 15:35 [PATCH 0/4] typec orientation switch support via mux controller Xu Yang
2022-08-22 15:35 ` [PATCH 1/4] dt-bindings: connector: Add typec orientation switch properties Xu Yang
2022-08-22 15:35 ` [PATCH 2/4] mux: allow get mux_control from fwnode if of_node is NULL Xu Yang
2022-08-23  6:23   ` Peter Rosin
2022-08-23 10:10     ` [EXT] " Xu Yang
2022-08-22 15:35 ` [PATCH 3/4] usb: typec: mux: add typec orientation switch support via mux controller Xu Yang
2022-08-22 11:22   ` kernel test robot
2022-08-22 15:46   ` kernel test robot
2022-08-23  5:13     ` [EXT] " Xu Yang
2022-08-23  6:13   ` Peter Rosin [this message]
2022-08-23  8:46     ` Xu Yang
2022-08-22 15:35 ` [PATCH 4/4] arm64: dts: imx8mp-evk: add typec node Xu Yang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c2261f2b-fa47-f988-bf5a-aaa3169c8c7e@axentia.se \
    --to=peda@axentia.se \
    --cc=devicetree@vger.kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=heikki.krogerus@linux.intel.com \
    --cc=jun.li@nxp.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-imx@nxp.com \
    --cc=linux-usb@vger.kernel.org \
    --cc=linux@roeck-us.net \
    --cc=robh+dt@kernel.org \
    --cc=shawnguo@kernel.org \
    --cc=xu.yang_2@nxp.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).