[PATCH V2 08/10] i3c: mipi-i3c-hci-pci: Convert to MFD driver
Frank Li
Frank.li at nxp.com
Thu Dec 11 08:18:05 PST 2025
On Thu, Dec 11, 2025 at 03:48:07PM +0200, Adrian Hunter wrote:
> Prepare for Multi-Bus instance support. Convert to MFD driver but still
> support only 1 instance.
>
> Signed-off-by: Adrian Hunter <adrian.hunter at intel.com>
> ---
Reviewed-by: Frank Li <Frank.Li at nxp.com>
>
>
> Changes in V2:
> New patch split from "i3c: mipi-i3c-hci-pci: Add support for
> Multi-Bus Instances"
>
>
> drivers/i3c/master/Kconfig | 1 +
> .../master/mipi-i3c-hci/mipi-i3c-hci-pci.c | 100 ++++++++++--------
> 2 files changed, 58 insertions(+), 43 deletions(-)
>
> diff --git a/drivers/i3c/master/Kconfig b/drivers/i3c/master/Kconfig
> index 82cf330778d5..2609f2b18e0a 100644
> --- a/drivers/i3c/master/Kconfig
> +++ b/drivers/i3c/master/Kconfig
> @@ -69,6 +69,7 @@ config MIPI_I3C_HCI_PCI
> tristate "MIPI I3C Host Controller Interface PCI support"
> depends on MIPI_I3C_HCI
> depends on PCI
> + select MFD_CORE
> help
> Support for MIPI I3C Host Controller Interface compatible hardware
> on the PCI bus.
> diff --git a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c
> index 0180d99a37e4..68088967942b 100644
> --- a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c
> +++ b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c
> @@ -12,6 +12,7 @@
> #include <linux/idr.h>
> #include <linux/iopoll.h>
> #include <linux/kernel.h>
> +#include <linux/mfd/core.h>
> #include <linux/module.h>
> #include <linux/pci.h>
> #include <linux/platform_data/mipi-i3c-hci.h>
> @@ -20,8 +21,8 @@
>
> struct mipi_i3c_hci_pci {
> struct pci_dev *pci;
> - struct platform_device *pdev;
> void __iomem *base;
> + int dev_id;
> const struct mipi_i3c_hci_pci_info *info;
> void *private;
> };
> @@ -178,13 +179,59 @@ static const struct mipi_i3c_hci_pci_info intel_info = {
> .exit = intel_i3c_exit,
> };
>
> +struct mipi_i3c_hci_pci_cell_data {
> + struct mipi_i3c_hci_platform_data pdata;
> + struct resource res;
> +};
> +
> +static void mipi_i3c_hci_pci_setup_cell(struct mipi_i3c_hci_pci *hci,
> + struct mipi_i3c_hci_pci_cell_data *data,
> + struct mfd_cell *cell)
> +{
> + data->pdata.base_regs = hci->base;
> +
> + data->res = DEFINE_RES_IRQ(0);
> +
> + cell->name = "mipi-i3c-hci";
> + cell->id = hci->dev_id;
> + cell->platform_data = &data->pdata;
> + cell->pdata_size = sizeof(data->pdata);
> + cell->num_resources = 1;
> + cell->resources = &data->res;
> +}
> +
> +static int mipi_i3c_hci_pci_add_instances(struct mipi_i3c_hci_pci *hci)
> +{
> + struct mipi_i3c_hci_pci_cell_data *data __free(kfree) = kzalloc(sizeof(*data), GFP_KERNEL);
> + struct mfd_cell *cells __free(kfree) = kzalloc(sizeof(*cells), GFP_KERNEL);
> + int irq = pci_irq_vector(hci->pci, 0);
> + int ret;
> +
> + if (!cells || !data)
> + return -ENOMEM;
> +
> + hci->dev_id = ida_alloc(&mipi_i3c_hci_pci_ida, GFP_KERNEL);
> + if (hci->dev_id < 0)
> + return hci->dev_id;
> +
> + mipi_i3c_hci_pci_setup_cell(hci, data, cells);
> +
> + ret = mfd_add_devices(&hci->pci->dev, 0, cells, 1, NULL, irq, NULL);
> + if (ret)
> + goto err_free_ids;
> +
> + return 0;
> +
> +err_free_ids:
> + ida_free(&mipi_i3c_hci_pci_ida, hci->dev_id);
> + return ret;
> +}
> +
> static int mipi_i3c_hci_pci_probe(struct pci_dev *pci,
> const struct pci_device_id *id)
> {
> - struct mipi_i3c_hci_platform_data pdata = {};
> struct mipi_i3c_hci_pci *hci;
> - struct resource res;
> - int dev_id, ret;
> + int ret;
>
> hci = devm_kzalloc(&pci->dev, sizeof(*hci), GFP_KERNEL);
> if (!hci)
> @@ -206,41 +253,13 @@ static int mipi_i3c_hci_pci_probe(struct pci_dev *pci,
> if (ret < 0)
> return ret;
>
> - memset(&res, 0, sizeof(res));
> -
> - res.flags = IORESOURCE_IRQ;
> - res.start = pci_irq_vector(hci->pci, 0);
> - res.end = res.start;
> -
> - dev_id = ida_alloc(&mipi_i3c_hci_pci_ida, GFP_KERNEL);
> - if (dev_id < 0)
> - return dev_id;
> -
> - hci->pdev = platform_device_alloc("mipi-i3c-hci", dev_id);
> - if (!hci->pdev)
> - return -ENOMEM;
> -
> - hci->pdev->dev.parent = &pci->dev;
> - device_set_node(&hci->pdev->dev, dev_fwnode(&pci->dev));
> -
> - ret = platform_device_add_resources(hci->pdev, &res, 1);
> - if (ret)
> - goto err;
> -
> - pdata.base_regs = hci->base;
> + hci->info = (const struct mipi_i3c_hci_pci_info *)id->driver_data;
>
> - ret = platform_device_add_data(hci->pdev, &pdata, sizeof(pdata));
> + ret = hci->info->init ? hci->info->init(hci) : 0;
> if (ret)
> - goto err;
> -
> - hci->info = (const struct mipi_i3c_hci_pci_info *)id->driver_data;
> - if (hci->info->init) {
> - ret = hci->info->init(hci);
> - if (ret)
> - goto err;
> - }
> + return ret;
>
> - ret = platform_device_add(hci->pdev);
> + ret = mipi_i3c_hci_pci_add_instances(hci);
> if (ret)
> goto err_exit;
>
> @@ -251,23 +270,18 @@ static int mipi_i3c_hci_pci_probe(struct pci_dev *pci,
> err_exit:
> if (hci->info->exit)
> hci->info->exit(hci);
> -err:
> - platform_device_put(hci->pdev);
> - ida_free(&mipi_i3c_hci_pci_ida, dev_id);
> return ret;
> }
>
> static void mipi_i3c_hci_pci_remove(struct pci_dev *pci)
> {
> struct mipi_i3c_hci_pci *hci = pci_get_drvdata(pci);
> - struct platform_device *pdev = hci->pdev;
> - int dev_id = pdev->id;
>
> if (hci->info->exit)
> hci->info->exit(hci);
>
> - platform_device_unregister(pdev);
> - ida_free(&mipi_i3c_hci_pci_ida, dev_id);
> + mfd_remove_devices(&pci->dev);
> + ida_free(&mipi_i3c_hci_pci_ida, hci->dev_id);
> }
>
> static const struct pci_device_id mipi_i3c_hci_pci_devices[] = {
> --
> 2.51.0
>
>
> --
> linux-i3c mailing list
> linux-i3c at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-i3c
More information about the linux-i3c
mailing list