[PATCH V2 08/10] i3c: mipi-i3c-hci-pci: Convert to MFD driver
Adrian Hunter
adrian.hunter at intel.com
Thu Dec 11 05:48:07 PST 2025
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>
---
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
More information about the linux-i3c
mailing list