All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jisheng Zhang <jszhang@kernel.org>
To: Richard Leitner <richard.leitner@linux.dev>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Rob Herring <robh@kernel.org>,
	Krzysztof Kozlowski <krzk+dt@kernel.org>,
	Conor Dooley <conor+dt@kernel.org>
Cc: linux-usb@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH 2/2] usb: usb251xb: support usage case without I2C control
Date: Fri, 15 Aug 2025 11:31:26 +0800	[thread overview]
Message-ID: <aJ6qDlumTAwwLMpN@xhacker> (raw)
In-Reply-To: <20250815025540.30575-3-jszhang@kernel.org>

On Fri, Aug 15, 2025 at 10:55:40AM +0800, Jisheng Zhang wrote:
> Refactor so that register writes for configuration are only performed if
> the device has a i2c_client provided and also register as a platform
> driver. This allows the driver to be used to manage GPIO based control
> of the device.
> 
> Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
> ---
>  drivers/usb/misc/usb251xb.c | 108 +++++++++++++++++++++++++++++++-----
>  1 file changed, 94 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/usb/misc/usb251xb.c b/drivers/usb/misc/usb251xb.c
> index 4fb453ca5450..ef5873009599 100644
> --- a/drivers/usb/misc/usb251xb.c
> +++ b/drivers/usb/misc/usb251xb.c
> @@ -17,6 +17,7 @@
>  #include <linux/module.h>
>  #include <linux/nls.h>
>  #include <linux/of.h>
> +#include <linux/platform_device.h>
>  #include <linux/regulator/consumer.h>
>  #include <linux/slab.h>
>  
> @@ -242,15 +243,19 @@ static int usb251xb_check_dev_children(struct device *dev, void *child)
>  static int usb251x_check_gpio_chip(struct usb251xb *hub)
>  {
>  	struct gpio_chip *gc = gpiod_to_chip(hub->gpio_reset);
> -	struct i2c_adapter *adap = hub->i2c->adapter;
> +	struct i2c_adapter *adap;
>  	int ret;
>  
> +	if (!hub->i2c)
> +		return 0;
> +
>  	if (!hub->gpio_reset)
>  		return 0;
>  
>  	if (!gc)
>  		return -EINVAL;
>  
> +	adap = hub->i2c->adapter;
>  	ret = usb251xb_check_dev_children(&adap->dev, gc->parent);
>  	if (ret) {
>  		dev_err(hub->dev, "Reset GPIO chip is at the same i2c-bus\n");
> @@ -271,7 +276,8 @@ static void usb251xb_reset(struct usb251xb *hub)
>  	if (!hub->gpio_reset)
>  		return;
>  
> -	i2c_lock_bus(hub->i2c->adapter, I2C_LOCK_SEGMENT);
> +	if (hub->i2c)
> +		i2c_lock_bus(hub->i2c->adapter, I2C_LOCK_SEGMENT);
>  
>  	gpiod_set_value_cansleep(hub->gpio_reset, 1);
>  	usleep_range(1, 10);	/* >=1us RESET_N asserted */
> @@ -280,7 +286,8 @@ static void usb251xb_reset(struct usb251xb *hub)
>  	/* wait for hub recovery/stabilization */
>  	usleep_range(500, 750);	/* >=500us after RESET_N deasserted */
>  
> -	i2c_unlock_bus(hub->i2c->adapter, I2C_LOCK_SEGMENT);
> +	if (hub->i2c)
> +		i2c_unlock_bus(hub->i2c->adapter, I2C_LOCK_SEGMENT);
>  }
>  
>  static int usb251xb_connect(struct usb251xb *hub)
> @@ -289,7 +296,11 @@ static int usb251xb_connect(struct usb251xb *hub)
>  	int err, i;
>  	char i2c_wb[USB251XB_I2C_REG_SZ];
>  
> -	memset(i2c_wb, 0, USB251XB_I2C_REG_SZ);
> +	if (!hub->i2c) {
> +		usb251xb_reset(hub);
> +		dev_info(dev, "hub is put in default configuration.\n");
> +		return 0;
> +	}
>  
>  	if (hub->skip_config) {
>  		dev_info(dev, "Skip hub configuration, only attach.\n");
> @@ -698,18 +709,13 @@ static int usb251xb_i2c_probe(struct i2c_client *i2c)
>  	return usb251xb_probe(hub);
>  }
>  
> -static int __maybe_unused usb251xb_suspend(struct device *dev)
> +static int usb251xb_suspend(struct usb251xb *hub)
>  {
> -	struct i2c_client *client = to_i2c_client(dev);
> -	struct usb251xb *hub = i2c_get_clientdata(client);
> -
>  	return regulator_disable(hub->vdd);
>  }
>  
> -static int __maybe_unused usb251xb_resume(struct device *dev)
> +static int usb251xb_resume(struct usb251xb *hub)
>  {
> -	struct i2c_client *client = to_i2c_client(dev);
> -	struct usb251xb *hub = i2c_get_clientdata(client);
>  	int err;
>  
>  	err = regulator_enable(hub->vdd);
> @@ -719,7 +725,23 @@ static int __maybe_unused usb251xb_resume(struct device *dev)
>  	return usb251xb_connect(hub);
>  }
>  
> -static SIMPLE_DEV_PM_OPS(usb251xb_pm_ops, usb251xb_suspend, usb251xb_resume);
> +static int usb251xb_i2c_suspend(struct device *dev)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	struct usb251xb *hub = i2c_get_clientdata(client);
> +
> +	return usb251xb_suspend(hub);
> +}
> +
> +static int usb251xb_i2c_resume(struct device *dev)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	struct usb251xb *hub = i2c_get_clientdata(client);
> +
> +	return usb251xb_resume(hub);
> +}
> +
> +static DEFINE_SIMPLE_DEV_PM_OPS(usb251xb_i2c_pm_ops, usb251xb_i2c_suspend, usb251xb_i2c_resume);

It seems this PM macros usage should be in a seperate patch. I will send a v2 this
night.

>  
>  static const struct i2c_device_id usb251xb_id[] = {
>  	{ "usb2422" },
> @@ -739,13 +761,71 @@ static struct i2c_driver usb251xb_i2c_driver = {
>  	.driver = {
>  		.name = DRIVER_NAME,
>  		.of_match_table = usb251xb_of_match,
> -		.pm = &usb251xb_pm_ops,
> +		.pm = pm_sleep_ptr(&usb251xb_i2c_pm_ops),
>  	},
>  	.probe = usb251xb_i2c_probe,
>  	.id_table = usb251xb_id,
>  };
>  
> -module_i2c_driver(usb251xb_i2c_driver);
> +static int usb251xb_plat_probe(struct platform_device *pdev)
> +{
> +	struct usb251xb *hub;
> +
> +	hub = devm_kzalloc(&pdev->dev, sizeof(*hub), GFP_KERNEL);
> +	if (!hub)
> +		return -ENOMEM;
> +
> +	platform_set_drvdata(pdev, hub);
> +	hub->dev = &pdev->dev;
> +
> +	return usb251xb_probe(hub);
> +}
> +
> +static int usb251xb_plat_suspend(struct device *dev)
> +{
> +	return usb251xb_suspend(dev_get_drvdata(dev));
> +}
> +
> +static int usb251xb_plat_resume(struct device *dev)
> +{
> +	return usb251xb_resume(dev_get_drvdata(dev));
> +}
> +
> +static DEFINE_SIMPLE_DEV_PM_OPS(usb251xb_plat_pm_ops, usb251xb_plat_suspend, usb251xb_plat_resume);
> +
> +static struct platform_driver usb251xb_plat_driver = {
> +	.driver = {
> +		.name = DRIVER_NAME,
> +		.of_match_table = of_match_ptr(usb251xb_of_match),
> +		.pm = pm_ptr(&usb251xb_plat_pm_ops),
> +	},
> +	.probe		= usb251xb_plat_probe,
> +};
> +
> +static int __init usb251xb_init(void)
> +{
> +	int err;
> +
> +	err = i2c_add_driver(&usb251xb_i2c_driver);
> +	if (err)
> +		return err;
> +
> +	err = platform_driver_register(&usb251xb_plat_driver);
> +	if (err) {
> +		i2c_del_driver(&usb251xb_i2c_driver);
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +module_init(usb251xb_init);
> +
> +static void __exit usb251xb_exit(void)
> +{
> +	platform_driver_unregister(&usb251xb_plat_driver);
> +	i2c_del_driver(&usb251xb_i2c_driver);
> +}
> +module_exit(usb251xb_exit);
>  
>  MODULE_AUTHOR("Richard Leitner <richard.leitner@skidata.com>");
>  MODULE_DESCRIPTION("USB251x/xBi USB 2.0 Hub Controller Driver");
> -- 
> 2.50.0
> 

      reply	other threads:[~2025-08-15  3:48 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-08-15  2:55 [PATCH 0/2] usb: usb251xb: support usage case without I2C control Jisheng Zhang
2025-08-15  2:55 ` [PATCH 1/2] dt-bindings: usb: usb251xb: make reg optional for no I2C ctrl use case Jisheng Zhang
2025-08-15  2:55 ` [PATCH 2/2] usb: usb251xb: support usage case without I2C control Jisheng Zhang
2025-08-15  3:31   ` Jisheng Zhang [this message]

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=aJ6qDlumTAwwLMpN@xhacker \
    --to=jszhang@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=krzk+dt@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=richard.leitner@linux.dev \
    --cc=robh@kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.