Commit b8460480 authored by Adrian Hunter's avatar Adrian Hunter Committed by Alexandre Belloni
Browse files

i3c: mipi-i3c-hci: Allow for Multi-Bus Instances



Add support for MIPI I3C Host Controllers with the Multi-Bus Instance
capability.  These controllers can host multiple I3C buses (up to 15)
within a single hardware function (e.g., PCIe B/D/F), providing one
indepedent HCI register set and corresponding I3C bus controller logic
per bus.

A separate platform device will represent each instance, but it is
necessary to allow for shared resources.

Multi-bus instances share the same MMIO address space, but the ranges are
not guaranteed to be contiguous. To avoid overlapping mappings, pass
base_regs from the parent mapping to child devices.

Allow the IRQ to be shared among instances.

Signed-off-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Reviewed-by: default avatarFrank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20260106164416.67074-8-adrian.hunter@intel.com


Signed-off-by: default avatarAlexandre Belloni <alexandre.belloni@bootlin.com>
parent 35c0bfe8
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/platform_data/mipi-i3c-hci.h>
#include <linux/platform_device.h>

#include "hci.h"
@@ -737,15 +738,27 @@ static int i3c_hci_init(struct i3c_hci *hci)

static int i3c_hci_probe(struct platform_device *pdev)
{
	const struct mipi_i3c_hci_platform_data *pdata = pdev->dev.platform_data;
	struct i3c_hci *hci;
	int irq, ret;

	hci = devm_kzalloc(&pdev->dev, sizeof(*hci), GFP_KERNEL);
	if (!hci)
		return -ENOMEM;

	/*
	 * Multi-bus instances share the same MMIO address range, but not
	 * necessarily in separate contiguous sub-ranges. To avoid overlapping
	 * mappings, provide base_regs from the parent mapping.
	 */
	if (pdata)
		hci->base_regs = pdata->base_regs;

	if (!hci->base_regs) {
		hci->base_regs = devm_platform_ioremap_resource(pdev, 0);
		if (IS_ERR(hci->base_regs))
			return PTR_ERR(hci->base_regs);
	}

	platform_set_drvdata(pdev, hci);
	/* temporary for dev_printk's, to be replaced in i3c_master_register */
@@ -759,7 +772,7 @@ static int i3c_hci_probe(struct platform_device *pdev)

	irq = platform_get_irq(pdev, 0);
	ret = devm_request_irq(&pdev->dev, irq, i3c_hci_irq_handler,
			       0, NULL, hci);
			       IRQF_SHARED, NULL, hci);
	if (ret)
		return ret;

+15 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef INCLUDE_PLATFORM_DATA_MIPI_I3C_HCI_H
#define INCLUDE_PLATFORM_DATA_MIPI_I3C_HCI_H

#include <linux/compiler_types.h>

/**
 * struct mipi_i3c_hci_platform_data - Platform-dependent data for mipi_i3c_hci
 * @base_regs: Register set base address (to support multi-bus instances)
 */
struct mipi_i3c_hci_platform_data {
	void __iomem *base_regs;
};

#endif