drivers/i2c/muxes/i2c-mux-reg.c | 75 ++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 43 deletions(-)
Convert the device-tree parsing path to the generic fwnode/device
property accessors so the driver can be probed on ACPI and swnode
platforms as well as OF. The helper is renamed from
i2c_mux_reg_probe_dt() to i2c_mux_reg_probe_fw() to reflect that.
Accessor translation:
of_parse_phandle("i2c-parent") +
of_find_i2c_adapter_by_node() -> fwnode_find_reference() +
i2c_get_adapter_by_fwnode()
of_get_child_count() -> device_get_child_node_count()
of_property_read_bool() -> device_property_read_bool()
for_each_child_of_node() -> device_for_each_child_node()
of_property_read_u32("reg") on OF: fwnode_property_read_u32()
on ACPI: acpi_get_local_address()
of_property_read_u32("idle-state") -> device_property_read_u32()
Behavioural preservations (deliberate, to avoid regressing existing
users):
- The three-way endian fallback is kept verbatim: an explicit
"little-endian" property wins, then "big-endian", and otherwise
the host's compile-time byte order. device_is_big_endian() is
not used here because it ignores "little-endian" and introduces
"native-endian" semantics, which would diverge from the binding.
- The platform-resource fallback for an un-mapped reg keeps its
"if (!mux->data.reg)" guard so a platdata user that supplies a
pre-ioremapped reg through struct i2c_mux_reg_platform_data is
not clobbered.
The OF-only of_address_to_resource() translation in the old
probe_dt() is dropped because the same address is available from
the platform_device resource table on both OF and ACPI, and the
existing fallback in probe() ioremaps it.
Signed-off-by: Abdurrahman Hussain <abdurrahman@nexthop.ai>
---
- Restore the original __BYTE_ORDER preprocessor check for the
endian-property fallback. v2 replaced it with
IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN), but that Kconfig symbol is
only defined on architectures with configurable endianness (arm,
arm64, mips, ppc, sh, xtensa, microblaze). On architectures where
endianness is fixed (x86, RISC-V, ...), the symbol is undefined,
IS_ENABLED() silently evaluates to false, and the mux defaults to
big-endian register writes. On a little-endian host that turns any
non-zero channel selection into garbage and quietly breaks every
slave behind the mux.
- Replace put_device(&adapter->dev) with i2c_put_adapter(adapter).
v1 switched from of_find_i2c_adapter_by_node() to
i2c_get_adapter_by_fwnode(); the new helper additionally takes a
try_module_get() on the adapter owner that put_device() alone does
not release. This leaked a module reference on every successful
probe.
- Read swnode child "reg" properties via fwnode_property_read_u32().
The previous loop branched on is_of_node()/is_acpi_node() only;
software nodes hit neither arm and silently left values[i] = 0,
giving every swnode channel index 0 and breaking channel mapping
on swnode platforms -- exactly the case the cover claims to add
support for.
i2c: mux: reg: use device property accessors
Convert the device-tree parsing path in i2c-mux-reg to the generic
fwnode/device property accessors so the driver can be probed on ACPI
and swnode platforms in addition to OF.
Changes in v2 (per Peter's review of v1 [1]):
- Restore the three-way endian-property fallback verbatim. v1 used
device_is_big_endian(), which ignores "little-endian" and adds
"native-endian" semantics -- a binding-visible behaviour change on
big-endian hosts that did not specify the property. v2 keeps the
original logic ("little-endian" wins, then "big-endian", else the
host's compile-time byte order), expressed via
device_property_read_bool() instead of of_property_read_bool().
- Restore the "if (!mux->data.reg)" guard around
devm_platform_get_and_ioremap_resource() in probe(). v1 dropped it
and would have clobbered the pre-ioremapped reg supplied by a
platdata user through struct i2c_mux_reg_platform_data.
- Restore the dev_err_probe() wrapper at the probe_fw() call site so
the silent error paths in the helper still produce a dmesg line on
failure.
- Rewrite the changelog to enumerate the accessor translations, the
new ACPI child-node handling via acpi_get_local_address(), and the
behavioural preservations above.
[1] https://lore.kernel.org/r/20260115003523.26660-1-abdurrahman@nexthop.ai
Link to v2: https://patch.msgid.link/20260512-i2c-mux-reg-v2-1-80ea1da4cd0a@nexthop.ai
---
drivers/i2c/muxes/i2c-mux-reg.c | 75 ++++++++++++++++++-----------------------
1 file changed, 32 insertions(+), 43 deletions(-)
diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c
index 1e566ea92bc9..8b35a50e2841 100644
--- a/drivers/i2c/muxes/i2c-mux-reg.c
+++ b/drivers/i2c/muxes/i2c-mux-reg.c
@@ -11,7 +11,6 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
-#include <linux/of_address.h>
#include <linux/platform_data/i2c-mux-reg.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -75,37 +74,34 @@ static int i2c_mux_reg_deselect(struct i2c_mux_core *muxc, u32 chan)
return 0;
}
-#ifdef CONFIG_OF
-static int i2c_mux_reg_probe_dt(struct regmux *mux,
- struct platform_device *pdev)
+static int i2c_mux_reg_probe_fw(struct regmux *mux, struct device *dev)
{
- struct device_node *np = pdev->dev.of_node;
- struct device_node *adapter_np, *child;
+ struct fwnode_handle *fwnode, *child;
struct i2c_adapter *adapter;
- struct resource res;
unsigned *values;
- int i = 0;
+ int ret, i = 0;
- if (!np)
+ if (!dev_fwnode(dev))
return -ENODEV;
- adapter_np = of_parse_phandle(np, "i2c-parent", 0);
- if (!adapter_np) {
- dev_err(&pdev->dev, "Cannot parse i2c-parent\n");
+ fwnode = fwnode_find_reference(dev_fwnode(dev), "i2c-parent", 0);
+ if (IS_ERR(fwnode)) {
+ dev_err(dev, "missing 'i2c-parent' property\n");
return -ENODEV;
}
- adapter = of_find_i2c_adapter_by_node(adapter_np);
- of_node_put(adapter_np);
+
+ adapter = i2c_get_adapter_by_fwnode(fwnode);
+ fwnode_handle_put(fwnode);
if (!adapter)
return -EPROBE_DEFER;
mux->data.parent = i2c_adapter_id(adapter);
- put_device(&adapter->dev);
+ i2c_put_adapter(adapter);
- mux->data.n_values = of_get_child_count(np);
- if (of_property_read_bool(np, "little-endian")) {
+ mux->data.n_values = device_get_child_node_count(dev);
+ if (device_property_read_bool(dev, "little-endian")) {
mux->data.little_endian = true;
- } else if (of_property_read_bool(np, "big-endian")) {
+ } else if (device_property_read_bool(dev, "big-endian")) {
mux->data.little_endian = false;
} else {
#if defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : \
@@ -118,40 +114,35 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,
#error Endianness not defined?
#endif
}
- mux->data.write_only = of_property_read_bool(np, "write-only");
+ mux->data.write_only = device_property_read_bool(dev, "write-only");
- values = devm_kcalloc(&pdev->dev,
- mux->data.n_values, sizeof(*mux->data.values),
+ values = devm_kcalloc(dev, mux->data.n_values, sizeof(*mux->data.values),
GFP_KERNEL);
if (!values)
return -ENOMEM;
- for_each_child_of_node(np, child) {
- of_property_read_u32(child, "reg", values + i);
+ device_for_each_child_node(dev, child) {
+ if (is_acpi_node(child)) {
+ ret = acpi_get_local_address(ACPI_HANDLE_FWNODE(child),
+ &values[i]);
+ if (ret) {
+ fwnode_handle_put(child);
+ return dev_err_probe(dev, ret,
+ "Cannot get address\n");
+ }
+ } else {
+ fwnode_property_read_u32(child, "reg", &values[i]);
+ }
+
i++;
}
mux->data.values = values;
- if (!of_property_read_u32(np, "idle-state", &mux->data.idle))
+ if (!device_property_read_u32(dev, "idle-state", &mux->data.idle))
mux->data.idle_in_use = true;
- /* map address from "reg" if exists */
- if (of_address_to_resource(np, 0, &res) == 0) {
- mux->data.reg_size = resource_size(&res);
- mux->data.reg = devm_ioremap_resource(&pdev->dev, &res);
- if (IS_ERR(mux->data.reg))
- return PTR_ERR(mux->data.reg);
- }
-
return 0;
}
-#else
-static int i2c_mux_reg_probe_dt(struct regmux *mux,
- struct platform_device *pdev)
-{
- return 0;
-}
-#endif
static int i2c_mux_reg_probe(struct platform_device *pdev)
{
@@ -169,10 +160,10 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
memcpy(&mux->data, dev_get_platdata(&pdev->dev),
sizeof(mux->data));
} else {
- ret = i2c_mux_reg_probe_dt(mux, pdev);
+ ret = i2c_mux_reg_probe_fw(mux, &pdev->dev);
if (ret < 0)
return dev_err_probe(&pdev->dev, ret,
- "Error parsing device tree");
+ "Error parsing firmware description\n");
}
parent = i2c_get_adapter(mux->data.parent);
@@ -180,8 +171,6 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
if (!mux->data.reg) {
- dev_info(&pdev->dev,
- "Register not set, using platform resource\n");
mux->data.reg = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(mux->data.reg)) {
ret = PTR_ERR(mux->data.reg);
---
base-commit: 254f49634ee16a731174d2ae34bc50bd5f45e731
change-id: 20260305-i2c-mux-reg-552203da8564
Best regards,
--
Abdurrahman Hussain <abdurrahman@nexthop.ai>
[retrying the change to peda@lysator.liu.se]
On 2026-05-14 02:54, Abdurrahman Hussain wrote:
> Convert the device-tree parsing path to the generic fwnode/device
> property accessors so the driver can be probed on ACPI and swnode
> platforms as well as OF. The helper is renamed from
> i2c_mux_reg_probe_dt() to i2c_mux_reg_probe_fw() to reflect that.
>
> Accessor translation:
>
> of_parse_phandle("i2c-parent") +
> of_find_i2c_adapter_by_node() -> fwnode_find_reference() +
> i2c_get_adapter_by_fwnode()
> of_get_child_count() -> device_get_child_node_count()
> of_property_read_bool() -> device_property_read_bool()
> for_each_child_of_node() -> device_for_each_child_node()
> of_property_read_u32("reg") on OF: fwnode_property_read_u32()
> on ACPI: acpi_get_local_address()
> of_property_read_u32("idle-state") -> device_property_read_u32()
>
> Behavioural preservations (deliberate, to avoid regressing existing
> users):
>
> - The three-way endian fallback is kept verbatim: an explicit
> "little-endian" property wins, then "big-endian", and otherwise
> the host's compile-time byte order. device_is_big_endian() is
> not used here because it ignores "little-endian" and introduces
> "native-endian" semantics, which would diverge from the binding.
>
> - The platform-resource fallback for an un-mapped reg keeps its
> "if (!mux->data.reg)" guard so a platdata user that supplies a
> pre-ioremapped reg through struct i2c_mux_reg_platform_data is
> not clobbered.
Hi!
After reading v2/v3, I finally got why you removed if (!mux->data.reg).
I.e., since you removed the io-remapping from i2c_mux_reg_probe_fw()
that part can now be unconditional in i2c_mux_reg_probe(). But,
keeping the if just to accomodate potential out-of-tree code that uses
the platform data hooking is not needed so v1 feels better than v2/v3.
Sorry for being dense. However, see below.
> The OF-only of_address_to_resource() translation in the old
> probe_dt() is dropped because the same address is available from
> the platform_device resource table on both OF and ACPI, and the
> existing fallback in probe() ioremaps it.
>
> Signed-off-by: Abdurrahman Hussain <abdurrahman@nexthop.ai>
> ---
> drivers/i2c/muxes/i2c-mux-reg.c | 75 ++++++++++++++++++-----------------------
> 1 file changed, 32 insertions(+), 43 deletions(-)
>
> diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c
> index 1e566ea92bc9..8b35a50e2841 100644
> --- a/drivers/i2c/muxes/i2c-mux-reg.c
> +++ b/drivers/i2c/muxes/i2c-mux-reg.c
> @@ -11,7 +11,6 @@
> #include <linux/init.h>
> #include <linux/io.h>
> #include <linux/module.h>
> -#include <linux/of_address.h>
> #include <linux/platform_data/i2c-mux-reg.h>
> #include <linux/platform_device.h>
> #include <linux/slab.h>
> @@ -75,37 +74,34 @@ static int i2c_mux_reg_deselect(struct i2c_mux_core *muxc, u32 chan)
> return 0;
> }
>
> -#ifdef CONFIG_OF
> -static int i2c_mux_reg_probe_dt(struct regmux *mux,
> - struct platform_device *pdev)
> +static int i2c_mux_reg_probe_fw(struct regmux *mux, struct device *dev)
> {
> - struct device_node *np = pdev->dev.of_node;
> - struct device_node *adapter_np, *child;
> + struct fwnode_handle *fwnode, *child;
> struct i2c_adapter *adapter;
> - struct resource res;
> unsigned *values;
> - int i = 0;
> + int ret, i = 0;
>
> - if (!np)
> + if (!dev_fwnode(dev))
> return -ENODEV;
>
> - adapter_np = of_parse_phandle(np, "i2c-parent", 0);
> - if (!adapter_np) {
> - dev_err(&pdev->dev, "Cannot parse i2c-parent\n");
> + fwnode = fwnode_find_reference(dev_fwnode(dev), "i2c-parent", 0);
> + if (IS_ERR(fwnode)) {
> + dev_err(dev, "missing 'i2c-parent' property\n");
> return -ENODEV;
> }
> - adapter = of_find_i2c_adapter_by_node(adapter_np);
> - of_node_put(adapter_np);
> +
> + adapter = i2c_get_adapter_by_fwnode(fwnode);
> + fwnode_handle_put(fwnode);
Why did you not change to i2c_find_adapter_by_fwnode()? It would be
closer to the original, but maybe that doesn't work for ACPI for some
reason?
> if (!adapter)
> return -EPROBE_DEFER;
>
> mux->data.parent = i2c_adapter_id(adapter);
> - put_device(&adapter->dev);
> + i2c_put_adapter(adapter);
>
> - mux->data.n_values = of_get_child_count(np);
> - if (of_property_read_bool(np, "little-endian")) {
> + mux->data.n_values = device_get_child_node_count(dev);
> + if (device_property_read_bool(dev, "little-endian")) {
> mux->data.little_endian = true;
> - } else if (of_property_read_bool(np, "big-endian")) {
> + } else if (device_property_read_bool(dev, "big-endian")) {
> mux->data.little_endian = false;
> } else {
> #if defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : \
> @@ -118,40 +114,35 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,
> #error Endianness not defined?
> #endif
> }
> - mux->data.write_only = of_property_read_bool(np, "write-only");
> + mux->data.write_only = device_property_read_bool(dev, "write-only");
>
> - values = devm_kcalloc(&pdev->dev,
> - mux->data.n_values, sizeof(*mux->data.values),
> + values = devm_kcalloc(dev, mux->data.n_values, sizeof(*mux->data.values),
> GFP_KERNEL);
> if (!values)
> return -ENOMEM;
>
> - for_each_child_of_node(np, child) {
> - of_property_read_u32(child, "reg", values + i);
> + device_for_each_child_node(dev, child) {
> + if (is_acpi_node(child)) {
> + ret = acpi_get_local_address(ACPI_HANDLE_FWNODE(child),
> + &values[i]);
> + if (ret) {
> + fwnode_handle_put(child);
> + return dev_err_probe(dev, ret,
> + "Cannot get address\n");
> + }
> + } else {
> + fwnode_property_read_u32(child, "reg", &values[i]);
> + }
> +
> i++;
> }
> mux->data.values = values;
>
> - if (!of_property_read_u32(np, "idle-state", &mux->data.idle))
> + if (!device_property_read_u32(dev, "idle-state", &mux->data.idle))
> mux->data.idle_in_use = true;
>
> - /* map address from "reg" if exists */
> - if (of_address_to_resource(np, 0, &res) == 0) {
> - mux->data.reg_size = resource_size(&res);
> - mux->data.reg = devm_ioremap_resource(&pdev->dev, &res);
> - if (IS_ERR(mux->data.reg))
> - return PTR_ERR(mux->data.reg);
> - }
> -
By not doing the io-remapping here, the ordering is now subtly altered.
Previously we had io-remapping before the call to i2c_get_adapter().
With this change we instead have the call to i2c_get_adapter() before
the io-remapping.
Since it is apparently difficult the get this patch tested for the
existing use cases, we should avoid as many of these innocent looking
but subtle changes as possible.
Cheers,
Peter
> return 0;
> }
> -#else
> -static int i2c_mux_reg_probe_dt(struct regmux *mux,
> - struct platform_device *pdev)
> -{
> - return 0;
> -}
> -#endif
>
> static int i2c_mux_reg_probe(struct platform_device *pdev)
> {
> @@ -169,10 +160,10 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
> memcpy(&mux->data, dev_get_platdata(&pdev->dev),
> sizeof(mux->data));
> } else {
> - ret = i2c_mux_reg_probe_dt(mux, pdev);
> + ret = i2c_mux_reg_probe_fw(mux, &pdev->dev);
> if (ret < 0)
> return dev_err_probe(&pdev->dev, ret,
> - "Error parsing device tree");
> + "Error parsing firmware description\n");
> }
>
> parent = i2c_get_adapter(mux->data.parent);
> @@ -180,8 +171,6 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
> return -EPROBE_DEFER;
>
> if (!mux->data.reg) {
> - dev_info(&pdev->dev,
> - "Register not set, using platform resource\n");
> mux->data.reg = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
> if (IS_ERR(mux->data.reg)) {
> ret = PTR_ERR(mux->data.reg);
>
> ---
> base-commit: 254f49634ee16a731174d2ae34bc50bd5f45e731
> change-id: 20260305-i2c-mux-reg-552203da8564
On Mon May 18, 2026 at 6:59 AM PDT, Peter Rosin wrote:
>
> Hi!
>
> After reading v2/v3, I finally got why you removed if (!mux->data.reg).
> I.e., since you removed the io-remapping from i2c_mux_reg_probe_fw()
> that part can now be unconditional in i2c_mux_reg_probe(). But,
> keeping the if just to accomodate potential out-of-tree code that uses
> the platform data hooking is not needed so v1 feels better than v2/v3.
> Sorry for being dense. However, see below.
>
Agreed -- v4 will drop the guard and make
devm_platform_get_and_ioremap_resource() unconditional.
Follow-up question while we're pruning the platdata path: with the
guard gone, the .reg and .reg_size fields in
struct i2c_mux_reg_platform_data are functionally dead (any value a
platdata user supplied through them is overwritten by
devm_platform_get_and_ioremap_resource()). Should I drop those two
fields from the struct in the same patch, or leave them as silent
no-ops in the public header? Happy either way.
>> - adapter = of_find_i2c_adapter_by_node(adapter_np);
>> - of_node_put(adapter_np);
>> +
>> + adapter = i2c_get_adapter_by_fwnode(fwnode);
>> + fwnode_handle_put(fwnode);
>
> Why did you not change to i2c_find_adapter_by_fwnode()? It would be
> closer to the original, but maybe that doesn't work for ACPI for some
> reason?
>
It works for ACPI -- both _find and _get bottom out in
i2c_find_adapter_by_fwnode(). My reason for picking the _get
variant was simply that it does try_module_get(adapter->owner) on
top. But i2c_get_adapter() further down in probe() already does
the same try_module_get() and -EPROBE_DEFERs on failure, so the
extra acquire-then-immediately-release in probe_fw() isn't earning
us anything. v4 will switch to i2c_find_adapter_by_fwnode() +
put_device(), matching the OF original more closely.
>> - /* map address from "reg" if exists */
>> - if (of_address_to_resource(np, 0, &res) == 0) {
>> - mux->data.reg_size = resource_size(&res);
>> - mux->data.reg = devm_ioremap_resource(&pdev->dev, &res);
>> - if (IS_ERR(mux->data.reg))
>> - return PTR_ERR(mux->data.reg);
>> - }
>> -
>
> By not doing the io-remapping here, the ordering is now subtly altered.
> Previously we had io-remapping before the call to i2c_get_adapter().
> With this change we instead have the call to i2c_get_adapter() before
> the io-remapping.
>
> Since it is apparently difficult the get this patch tested for the
> existing use cases, we should avoid as many of these innocent looking
> but subtle changes as possible.
>
> Cheers,
> Peter
>
Will fix that in v4 by reordering probe() so the
devm_platform_get_and_ioremap_resource() call comes before
i2c_get_adapter(), matching the master sequence. No need to push
the ioremap back into probe_fw() -- the helper signature stays
cleaner if probe() owns the call.
Thanks for the careful re-read.
Cheers,
Abdurrahman
On Mon May 18, 2026 at 1:15 PM PDT, Abdurrahman Hussain wrote:
> On Mon May 18, 2026 at 6:59 AM PDT, Peter Rosin wrote:
>>
>> Hi!
>>
>> After reading v2/v3, I finally got why you removed if (!mux->data.reg).
>> I.e., since you removed the io-remapping from i2c_mux_reg_probe_fw()
>> that part can now be unconditional in i2c_mux_reg_probe(). But,
>> keeping the if just to accomodate potential out-of-tree code that uses
>> the platform data hooking is not needed so v1 feels better than v2/v3.
>> Sorry for being dense. However, see below.
>>
>
> Agreed -- v4 will drop the guard and make
> devm_platform_get_and_ioremap_resource() unconditional.
>
> Follow-up question while we're pruning the platdata path: with the
> guard gone, the .reg and .reg_size fields in
> struct i2c_mux_reg_platform_data are functionally dead (any value a
> platdata user supplied through them is overwritten by
> devm_platform_get_and_ioremap_resource()). Should I drop those two
> fields from the struct in the same patch, or leave them as silent
> no-ops in the public header? Happy either way.
>
Scratch that, sorry -- right after sending I noticed
drivers/platform/mellanox/mlx-platform.c is an in-tree platdata
user. It registers i2c-mux-reg platform_devices via
platform_device_register_resndata(..., res=NULL, num_res=0, ...)
and supplies a pre-set .reg (a (void __iomem *) cast of an LPC
register address) and .reg_size=1 through the platdata struct
(mlxplat_default_mux_data[] and friends around line 474).
Without the if (!mux->data.reg) guard,
devm_platform_get_and_ioremap_resource() would run unconditionally,
fail because the pdev carries no memory resource, and break
mlx-platform's mux probe. v4 will therefore keep the guard, and
the .reg / .reg_size fields stay in the public platdata struct.
The other two changes stand:
- i2c_get_adapter_by_fwnode() -> i2c_find_adapter_by_fwnode() +
put_device() in probe_fw(), matching the OF original.
- In probe(), move the if (!mux->data.reg) ioremap block --
together with the reg_size validation that depends on it --
above the i2c_get_adapter() call. fwnode users get back the
master-side ordering of "ioremap before parent-adapter get";
platdata users see the size check run a bit earlier, but
mux->data.reg_size is set from platdata by then, so it's
order-neutral for them.
Cheers,
Abdurrahman
>>> - adapter = of_find_i2c_adapter_by_node(adapter_np);
>>> - of_node_put(adapter_np);
>>> +
>>> + adapter = i2c_get_adapter_by_fwnode(fwnode);
>>> + fwnode_handle_put(fwnode);
>>
>> Why did you not change to i2c_find_adapter_by_fwnode()? It would be
>> closer to the original, but maybe that doesn't work for ACPI for some
>> reason?
>>
>
> It works for ACPI -- both _find and _get bottom out in
> i2c_find_adapter_by_fwnode(). My reason for picking the _get
> variant was simply that it does try_module_get(adapter->owner) on
> top. But i2c_get_adapter() further down in probe() already does
> the same try_module_get() and -EPROBE_DEFERs on failure, so the
> extra acquire-then-immediately-release in probe_fw() isn't earning
> us anything. v4 will switch to i2c_find_adapter_by_fwnode() +
> put_device(), matching the OF original more closely.
>
>>> - /* map address from "reg" if exists */
>>> - if (of_address_to_resource(np, 0, &res) == 0) {
>>> - mux->data.reg_size = resource_size(&res);
>>> - mux->data.reg = devm_ioremap_resource(&pdev->dev, &res);
>>> - if (IS_ERR(mux->data.reg))
>>> - return PTR_ERR(mux->data.reg);
>>> - }
>>> -
>>
>> By not doing the io-remapping here, the ordering is now subtly altered.
>> Previously we had io-remapping before the call to i2c_get_adapter().
>> With this change we instead have the call to i2c_get_adapter() before
>> the io-remapping.
>>
>> Since it is apparently difficult the get this patch tested for the
>> existing use cases, we should avoid as many of these innocent looking
>> but subtle changes as possible.
>>
>> Cheers,
>> Peter
>>
>
> Will fix that in v4 by reordering probe() so the
> devm_platform_get_and_ioremap_resource() call comes before
> i2c_get_adapter(), matching the master sequence. No need to push
> the ioremap back into probe_fw() -- the helper signature stays
> cleaner if probe() owns the call.
>
> Thanks for the careful re-read.
>
> Cheers,
> Abdurrahman
© 2016 - 2026 Red Hat, Inc.