[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