Devicetree
 help / color / mirror / Atom feed
From: Krzysztof Kozlowski <krzk@kernel.org>
To: Lakshay Piplani <lakshay.piplani@nxp.com>,
	linux-kernel@vger.kernel.org, linux-i3c@lists.infradead.org,
	alexandre.belloni@bootlin.com, krzk+dt@kernel.org,
	robh@kernel.org, conor+dt@kernel.org, devicetree@vger.kernel.org,
	broonie@kernel.org, lee@kernel.org, Frank.Li@nxp.com,
	lgirdwood@gmail.com
Cc: vikash.bansal@nxp.com, priyanka.jain@nxp.com, aman.kumarpandey@nxp.com
Subject: Re: [PATCH v16 7/8] i3c: hub: p3h2x4x: Add support for NXP P3H2x4x I3C hub functionality
Date: Thu, 27 Aug 2026 12:16:46 +0200	[thread overview]
Message-ID: <91090730-b8b5-4346-a151-c11489abf2b3@kernel.org> (raw)
In-Reply-To: <20260826103819.1614843-8-lakshay.piplani@nxp.com>

On 26/08/2026 12:38, Lakshay Piplani wrote:
> +
> +static int p3h2x4x_configure_ldo(struct device *dev)
> +{
> +	static const char * const supplies[] = {
> +		"vcc1",
> +		"vcc2",
> +		"vcc3",
> +		"vcc4"
> +	};
> +	int ret, i;
> +
> +	for (i = 0; i < ARRAY_SIZE(supplies); i++) {
> +		ret = devm_regulator_get_enable_optional(dev, supplies[i]);
> +		if (ret && ret != -ENODEV)
> +			return dev_err_probe(dev, ret, "Failed to enable %s\n",
> +					     supplies[i]);
> +	}
> +
> +	/* This delay is required for the regulator to stabilize its output voltage */
> +	fsleep(5000);

Instead your regulators miss ramp delays.

> +
> +	return 0;
> +}


...

> +
> +static void p3h2x4x_get_target_port_dt_conf(struct device *dev,
> +					    const struct device_node *node)
> +{
> +	struct p3h2x4x_i3c_hub_dev *p3h2x4x_i3c_hub = dev_get_drvdata(dev);
> +	struct p3h2x4x *p3h2x4x = dev_get_drvdata(dev->parent);
> +	u64 tp_port;
> +
> +	for_each_available_child_of_node_scoped(node, dev_node) {

Why do you need scoped loop?

> +		if (of_property_read_reg(dev_node, 0, &tp_port, NULL))
> +			continue;
> +
> +		if (tp_port < p3h2x4x->num_target_ports) {
> +			if (p3h2x4x_i3c_hub->tp_bus[tp_port].of_node) {
> +				dev_warn(dev, "Duplicate target port %llu in DT\n", tp_port);
> +				continue;
> +			}
> +
> +			p3h2x4x_i3c_hub->tp_bus[tp_port].of_node = of_node_get(dev_node);
> +			p3h2x4x_i3c_hub->tp_bus[tp_port].tp_mask = P3H2X4X_SET_BIT(tp_port);
> +			p3h2x4x_i3c_hub->tp_bus[tp_port].p3h2x4x_i3c_hub = p3h2x4x_i3c_hub;
> +			p3h2x4x_i3c_hub->tp_bus[tp_port].tp_port = tp_port;
> +		}
> +	}
> +}
> +
> +static int p3h2x4x_parse_tp_dt_settings(struct device *dev,
> +					const struct device_node *node,
> +					struct tp_configuration tp_config[])
> +{
> +	struct p3h2x4x *p3h2x4x = dev_get_drvdata(dev->parent);
> +	u64 id;
> +	int ret;
> +
> +	for_each_available_child_of_node_scoped(node, tp_node) {
> +		enum p3h2x4x_tp_mode mode;
> +
> +		/*
> +		 * Only "i3c" and "smbus" children describe target ports. Skip any
> +		 * other child (for example the MFD "regulators" container), which
> +		 * has no "reg" property.
> +		 */
> +		if (of_node_name_eq(tp_node, "i3c"))
> +			mode = P3H2X4X_TP_MODE_I3C;
> +		else if (of_node_name_eq(tp_node, "smbus"))
> +			mode = P3H2X4X_TP_MODE_SMBUS;
> +		else
> +			continue;
> +
> +		ret = of_property_read_reg(tp_node, 0, &id, NULL);
> +		if (ret)
> +			return dev_err_probe(dev, ret,
> +					     "Failed to read reg for %pOF\n",
> +					     tp_node);
> +
> +		if (id >= p3h2x4x->num_target_ports)
> +			return dev_err_probe(dev, -EINVAL,
> +					     "Invalid target port index %llu\n",
> +					     id);
> +
> +		tp_config[id].mode = mode;
> +		tp_config[id].pullup_en =
> +			of_property_read_bool(tp_node, "nxp,pullup-enable");
> +	}
> +
> +	return 0;
> +}
> +
> +static int p3h2x4x_get_hub_dt_conf(struct device *dev,
> +				   const struct device_node *node)
> +{
> +	struct p3h2x4x_i3c_hub_dev *p3h2x4x_i3c_hub = dev_get_drvdata(dev);
> +
> +	of_property_read_u32(node, "nxp,tp0145-pullup-ohms",
> +			     &p3h2x4x_i3c_hub->hub_config.tp0145_pullup);
> +	of_property_read_u32(node, "nxp,tp2367-pullup-ohms",
> +			     &p3h2x4x_i3c_hub->hub_config.tp2367_pullup);
> +	of_property_read_u32(node, "nxp,cp0-io-strength-ohms",
> +			     &p3h2x4x_i3c_hub->hub_config.cp0_io_strength);
> +	of_property_read_u32(node, "nxp,cp1-io-strength-ohms",
> +			     &p3h2x4x_i3c_hub->hub_config.cp1_io_strength);
> +	of_property_read_u32(node, "nxp,tp0145-io-strength-ohms",
> +			     &p3h2x4x_i3c_hub->hub_config.tp0145_io_strength);
> +	of_property_read_u32(node, "nxp,tp2367-io-strength-ohms",
> +			     &p3h2x4x_i3c_hub->hub_config.tp2367_io_strength);
> +
> +	return p3h2x4x_parse_tp_dt_settings(dev, node,
> +					    p3h2x4x_i3c_hub->hub_config.tp_config);
> +}
> +
> +static void p3h2x4x_default_configuration(struct device *dev)
> +{
> +	struct p3h2x4x_i3c_hub_dev *p3h2x4x_i3c_hub = dev_get_drvdata(dev);
> +	int tp_count;
> +
> +	p3h2x4x_i3c_hub->hub_config.tp0145_pullup = P3H2X4X_DFT_TP_PULLUP_OHMS;
> +	p3h2x4x_i3c_hub->hub_config.tp2367_pullup = P3H2X4X_DFT_TP_PULLUP_OHMS;
> +	p3h2x4x_i3c_hub->hub_config.cp0_io_strength = P3H2X4X_DFT_IO_STRENGTH_OHMS;
> +	p3h2x4x_i3c_hub->hub_config.cp1_io_strength = P3H2X4X_DFT_IO_STRENGTH_OHMS;
> +	p3h2x4x_i3c_hub->hub_config.tp0145_io_strength = P3H2X4X_DFT_IO_STRENGTH_OHMS;
> +	p3h2x4x_i3c_hub->hub_config.tp2367_io_strength = P3H2X4X_DFT_IO_STRENGTH_OHMS;
> +
> +	for (tp_count = 0; tp_count < P3H2X4X_TP_MAX_COUNT; ++tp_count)
> +		p3h2x4x_i3c_hub->hub_config.tp_config[tp_count].mode = P3H2X4X_TP_MODE_I3C;
> +}
> +
> +static void p3h2x4x_unregister_smbus_adapters_action(void *data)
> +{
> +	p3h2x4x_unregister_smbus_adapters(data);
> +}
> +
> +static void p3h2x4x_put_target_port_of_nodes(void *data)
> +{
> +	struct p3h2x4x_i3c_hub_dev *hub = data;
> +	int tp;
> +
> +	for (tp = 0; tp < P3H2X4X_TP_MAX_COUNT; tp++) {
> +		of_node_put(hub->tp_bus[tp].of_node);
> +		hub->tp_bus[tp].of_node = NULL;
> +	}
> +}
> +
> +static void p3h2x4x_clear_i3c_hub_priv(void *data)
> +{
> +	struct p3h2x4x *p3h2x4x = data;
> +
> +	/* Drop the IBI handler backpointer; see the ordering note at the registration site. */
> +	p3h2x4x->i3c_hub_priv = NULL;
> +}
> +
> +static int p3h2x4x_i3c_hub_probe(struct platform_device *pdev)
> +{
> +	struct p3h2x4x *p3h2x4x = dev_get_drvdata(pdev->dev.parent);
> +	struct p3h2x4x_i3c_hub_dev *p3h2x4x_i3c_hub;
> +	struct device *dev = &pdev->dev;
> +	struct device_node *node;
> +	int ret, i;
> +
> +	p3h2x4x_i3c_hub = devm_kzalloc(dev, sizeof(*p3h2x4x_i3c_hub), GFP_KERNEL);
> +	if (!p3h2x4x_i3c_hub)
> +		return -ENOMEM;
> +
> +	p3h2x4x_i3c_hub->regmap = p3h2x4x->regmap;
> +	p3h2x4x_i3c_hub->dev = dev;
> +
> +	platform_set_drvdata(pdev, p3h2x4x_i3c_hub);
> +	device_set_of_node_from_dev(dev, dev->parent);
> +
> +	p3h2x4x_default_configuration(dev);
> +
> +	ret = devm_mutex_init(dev, &p3h2x4x_i3c_hub->etx_mutex);
> +	if (ret)
> +		return ret;
> +
> +	for (i = 0; i < P3H2X4X_TP_MAX_COUNT; i++) {
> +		ret = devm_mutex_init(dev, &p3h2x4x_i3c_hub->tp_bus[i].port_mutex);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	/* get hub node from DT */
> +	node = dev_of_node(dev);
> +	if (!node)
> +		return dev_err_probe(dev, -ENODEV, "No Device Tree entry found\n");
> +
> +	ret = p3h2x4x_get_hub_dt_conf(dev, node);
> +	if (ret)
> +		return ret;
> +
> +	p3h2x4x_get_target_port_dt_conf(dev, node);
> +
> +	ret = devm_add_action_or_reset(dev,
> +				       p3h2x4x_put_target_port_of_nodes,
> +				       p3h2x4x_i3c_hub);
> +	if (ret)
> +		return ret;
> +
> +	ret = p3h2x4x_configure_hw(dev);
> +	if (ret)
> +		return dev_err_probe(dev, ret, "Failed to configure the HUB\n");
> +
> +	/* Register virtual I3C master controllers for I3C target ports */
> +	if (p3h2x4x->i3cdev) {
> +		p3h2x4x_i3c_hub->i3cdev = p3h2x4x->i3cdev;
> +		/*
> +		 * Publish the hub context in the MFD parent struct rather than
> +		 * via i3cdev_set_drvdata(), which would overwrite the parent's
> +		 * drvdata (struct p3h2x4x) that the IBI handler and other MFD
> +		 * callbacks rely on. Publish it before p3h2x4x_tp_i3c_algo()
> +		 * enables IBI, since the IBI handler dereferences it.
> +		 */
> +		p3h2x4x->i3c_hub_priv = p3h2x4x_i3c_hub;
> +
> +		/*
> +		 * Register the clear action before enabling IBI so that, on the
> +		 * devm LIFO unwind (probe failure or removal), the pointer is
> +		 * cleared only after IBI has been disabled and freed.
> +		 */
> +		ret = devm_add_action_or_reset(dev, p3h2x4x_clear_i3c_hub_priv,
> +					       p3h2x4x);
> +		if (ret)
> +			return ret;
> +
> +		ret = p3h2x4x_tp_i3c_algo(p3h2x4x_i3c_hub);
> +		if (ret)
> +			return dev_err_probe(dev, ret, "Failed to register i3c bus\n");
> +	}
> +
> +	/* Register virtual I2C adapters for SMBus target ports */
> +	ret = p3h2x4x_tp_smbus_algo(p3h2x4x_i3c_hub);
> +	if (ret)
> +		return dev_err_probe(dev, ret, "Failed to add i2c adapter\n");
> +
> +	ret = devm_add_action_or_reset(dev,
> +				       p3h2x4x_unregister_smbus_adapters_action,
> +				       p3h2x4x_i3c_hub);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static const struct platform_device_id p3h2x4x_i3c_hub_id[] = {
> +	{ "p3h2x4x-i3c-hub" },

Use named initializers. In every patch of yours.

> +	{ }
> +};

..


> +
> +/**
> + * p3h2x4x_tp_i3c_algo - Register I3C virtual masters for I3C target ports.
> + * @p3h2x4x_hub: p3h2x4x device structure.
> + * Return: 0 in case of success, negative error code on failure.
> + */
> +int p3h2x4x_tp_i3c_algo(struct p3h2x4x_i3c_hub_dev *p3h2x4x_hub)
> +{
> +	struct i3c_master_controller *parent = i3c_dev_get_master(p3h2x4x_hub->i3cdev->desc);
> +	struct p3h2x4x *p3h2x4x = dev_get_drvdata(p3h2x4x_hub->dev->parent);
> +	u8 tp, ntwk_mask = 0;
> +	int ret;
> +
> +	p3h2x4x_hub->hub = devm_kzalloc(p3h2x4x_hub->dev,
> +					sizeof(*p3h2x4x_hub->hub),
> +					GFP_KERNEL);
> +

In multiple places you added blank lines between the call and if()
check. Don't.

> +	if (!p3h2x4x_hub->hub)
> +		return -ENOMEM;


Best regards,
Krzysztof

  reply	other threads:[~2026-08-27 10:16 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-26 10:38 [PATCH v16 0/8] Add support for NXP P3H2x4x I3C hub driver Lakshay Piplani
2026-08-26 10:38 ` [PATCH v16 1/8] i3c: master: Add APIs for I3C hub support Lakshay Piplani
2026-08-26 10:52   ` sashiko-bot
2026-08-26 16:36   ` Frank Li
2026-08-26 10:38 ` [PATCH v16 2/8] i3c: master: Add controller-only device operation helpers Lakshay Piplani
2026-08-26 10:50   ` sashiko-bot
2026-08-26 16:42   ` Frank Li
2026-08-27  7:02     ` Lakshay Piplani
2026-08-26 10:38 ` [PATCH v16 3/8] dt-bindings: i3c: Add NXP P3H2x4x i3c-hub support Lakshay Piplani
2026-08-26 10:38 ` [PATCH v16 4/8] mfd: p3h2x4x: Add driver for NXP P3H2x4x i3c hub and on-die regulator Lakshay Piplani
2026-08-26 10:56   ` sashiko-bot
2026-08-27 10:03   ` Krzysztof Kozlowski
2026-08-26 10:38 ` [PATCH v16 5/8] regulator: p3h2x4x: Add driver for on-die regulators in NXP P3H2x4x i3c hub Lakshay Piplani
2026-08-26 10:48   ` sashiko-bot
2026-08-26 10:38 ` [PATCH v16 6/8] i3c: hub: Add support for the I3C interface in the I3C hub Lakshay Piplani
2026-08-26 11:04   ` sashiko-bot
2026-08-26 17:02     ` Frank Li
2026-08-27  7:07       ` Lakshay Piplani
2026-08-27 10:09   ` Krzysztof Kozlowski
2026-08-26 10:38 ` [PATCH v16 7/8] i3c: hub: p3h2x4x: Add support for NXP P3H2x4x I3C hub functionality Lakshay Piplani
2026-08-27 10:16   ` Krzysztof Kozlowski [this message]
2026-08-26 10:38 ` [PATCH v16 8/8] i3c: hub: p3h2x4x: Add SMBus slave mode support Lakshay Piplani

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=91090730-b8b5-4346-a151-c11489abf2b3@kernel.org \
    --to=krzk@kernel.org \
    --cc=Frank.Li@nxp.com \
    --cc=alexandre.belloni@bootlin.com \
    --cc=aman.kumarpandey@nxp.com \
    --cc=broonie@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=krzk+dt@kernel.org \
    --cc=lakshay.piplani@nxp.com \
    --cc=lee@kernel.org \
    --cc=lgirdwood@gmail.com \
    --cc=linux-i3c@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=priyanka.jain@nxp.com \
    --cc=robh@kernel.org \
    --cc=vikash.bansal@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