Thread (33 messages) 33 messages, 6 authors, 2025-06-25

Re: [PATCH v12 1/7] mfd: Add core driver for Nuvoton NCT6694

From: Lee Jones <lee@kernel.org>
Date: 2025-06-25 14:53:28
Also in: linux-can, linux-gpio, linux-hwmon, linux-i2c, linux-rtc, linux-usb, linux-watchdog, lkml

[...]
quoted
quoted
quoted
quoted
quoted
In the code above you register 6 I2C devices.  Each device will be
assigned a platform ID 0 through 5. The .probe() function in the I2C
driver will be executed 6 times.  In each of those calls to .probe(),
instead of pre-allocating a contiguous assignment of IDs here, you
should be able to use IDA in .probe() to allocate those same device IDs
0 through 5.

What am I missing here?
You're absolutely right in the scenario where a single NCT6694 device
is present. However, I’m wondering how we should handle the case where
a second or even third NCT6694 device is bound to the same MFD driver.
In that situation, the sub-drivers using a static IDA will continue
allocating increasing IDs, rather than restarting from 0 for each
device. How should this be handled?
I'd like to see the implementation of this before advising.

In such a case, I assume there would be a differentiating factor between
the two (or three) devices.  You would then use that to decide which IDA
would need to be incremented.

However, Greg is correct.  Hard-coding look-ups for userspace to use
sounds like a terrible idea.
I understand.
Do you think it would be better to pass the index via platform_data
and use PLATFORM_DEVID_AUTO together with mfd_add_hotplug_devices()
instead?
For example:
struct nct6694_platform_data {
    int index;
};

static struct nct6694_platform_data i2c_data[] = {
    { .index = 0 }, { .index = 1 }, { .index = 2 }, { .index = 3 }, {
.index = 4 }, { .index = 5 },
};

static const struct mfd_cell nct6694_devs[] = {
    MFD_CELL_BASIC("nct6694-i2c", NULL, &i2c_data[0], sizeof(struct
nct6694_platform_data), 0),
    MFD_CELL_BASIC("nct6694-i2c", NULL, &i2c_data[1], sizeof(struct
nct6694_platform_data), 0),
    MFD_CELL_BASIC("nct6694-i2c", NULL, &i2c_data[2], sizeof(struct
nct6694_platform_data), 0),
    MFD_CELL_BASIC("nct6694-i2c", NULL, &i2c_data[3], sizeof(struct
nct6694_platform_data), 0),
    MFD_CELL_BASIC("nct6694-i2c", NULL, &i2c_data[4], sizeof(struct
nct6694_platform_data), 0),
    MFD_CELL_BASIC("nct6694-i2c", NULL, &i2c_data[5], sizeof(struct
nct6694_platform_data), 0),
};
...
mfd_add_hotplug_devices(dev, nct6694_devs, ARRAY_SIZE(nct6694_devs));
...
No, that's clearly way worse.  =:-)

The clean-up that this provides is probably not worth all of this
discussion.  I _still_ think this enumeration should be done in the
driver.  But if you really can't make it work, I'll accept the .id
patch.
Okay, I would like to ask for your advice regarding the implementation of IDA.

Using a global IDA in the sub-driver like this:
(in i2c-nct6694.c)
static DEFINE_IDA(nct6694_i2c_ida);

static int nct6694_i2c_probe(struct platform_device *pdev)
{
    ida_alloc(&nct6694_i2c_ida, GFP_KERNEL);
    ...
}

causes IDs to be globally incremented across all devices. For example,
the first NCT6694 device gets probed 6 times and receives IDs 0–5, but
when a second NCT6694 device is added, it receives IDs starting from
6, rather than starting again from 0. This makes per-device ID mapping
unreliable.

To solve this, I believe the right approach is to have each NCT6694
instance maintain its own IDA, managed by the MFD driver's private
data. As mentioned earlier, for example:
(in nct6694.c)
struct nct6694 {
    struct device *dev;
    struct ida i2c_ida;
};

static int nct6694_probe(struct platform_device *pdev)
{
    ...
    ida_init(&nct6694->i2c_ida);
    ...
}

(in i2c-nct6694.c)
static int nct6694_i2c_probe(struct platform_device *pdev)
{
    id = ida_alloc(&nct6694->i2c_ida, GFP_KERNEL);
}

This way, each device allocates IDs independently, and each set of
I2C/GPIO instances gets predictable IDs starting from 0 per device. I
think this resolves the original issue without relying on hardcoded
platform IDs.
Please let me know if this implementation aligns with what you had in mind.
This sounds like an acceptable way forward.

-- 
Lee Jones [李琼斯]
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help