From nobody Sun Feb 8 04:13:12 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3D40C277022 for ; Wed, 14 May 2025 12:26:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.17 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747225590; cv=none; b=Ghusfhb0JWBF8qo7DNq9CNmlGBMgTKt98bYq2KU58dmnBCdthzE6UP71UQUxOivUYofml6O++ekSuVqZCkroMUi4yGoKPWrcKtw1eJ5zrZmdDOEovGzwW1MXivfh4hq59DpHHEO6JKgHOFOt4gAl2bjtnfY1WZ9ZyzN52uQIjJs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747225590; c=relaxed/simple; bh=tLUloUpo2WCG1fHm5KAQ4cVvj5x7S6Ccu+wBGNb++OQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=KrLFTiz+kqLNRo83IPeckgtylsh4DHIM0o4arnynwkp8qvyCjLZBf+CVfZ1QsrRX0g7UMybJcWo0uZI+SpefKZ7+1asio2e825wAvb+7zhZftj/wgga0yxrtx9cJK7mTqJ19VhnNWuYQ/+wnhUBRHzOKuYfxwhy27Y9DGTxff+U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=XU7bDYtp; arc=none smtp.client-ip=198.175.65.17 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="XU7bDYtp" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1747225588; x=1778761588; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=tLUloUpo2WCG1fHm5KAQ4cVvj5x7S6Ccu+wBGNb++OQ=; b=XU7bDYtpj6AnbnHloT9DT4ys9vmtnMRld1QhkuOs82iSbL04TQQ7fwzC UU+Imri0ut/GmgrOkwCHsybHoVtJhniymKhcb8rkGvd0bfbo7WTaWu5wL tfVnRV9ZDHXHq2ttUr3uGlltBG8z+herjFlMiECc5W3MgX9U0yevV+fne ZOYTVNVKJAjgpWaoeUxulIbSIR2rwk6MYoRbomHvm6d80NaopTravOIna DOc5bDSvikqiER3cq6pu+uS1ZasaWAdIRWk3UxLmpKId8Gd7I9DEmuiZz YemLNWzmqat5TxK2hKqsrhl2NwRfR6Lys6zuYK7uGg/mFq7h9AZAQ8lqR g==; X-CSE-ConnectionGUID: DB28z25pQuavixuqid4ZdQ== X-CSE-MsgGUID: 9LDfr7r9SqOr6Au/H2oOEQ== X-IronPort-AV: E=McAfee;i="6700,10204,11433"; a="49098847" X-IronPort-AV: E=Sophos;i="6.15,288,1739865600"; d="scan'208";a="49098847" Received: from orviesa006.jf.intel.com ([10.64.159.146]) by orvoesa109.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 May 2025 05:26:28 -0700 X-CSE-ConnectionGUID: n4AnYIgeSPqVd/ksF3J46g== X-CSE-MsgGUID: BbbOVRwXTfi1bE+fdj39IQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.15,288,1739865600"; d="scan'208";a="137946718" Received: from jraag-z790m-itx-wifi.iind.intel.com ([10.190.239.23]) by orviesa006.jf.intel.com with ESMTP; 14 May 2025 05:26:25 -0700 From: Raag Jadav To: gregkh@linuxfoundation.org, david.m.ertman@intel.com, ira.weiny@intel.com, lee@kernel.org, andriy.shevchenko@linux.intel.com, mika.westerberg@linux.intel.com, heikki.krogerus@linux.intel.com Cc: linux-kernel@vger.kernel.org, Raag Jadav Subject: [PATCH v5 1/2] driver core: auxiliary bus: Introduce auxiliary device resource management Date: Wed, 14 May 2025 17:54:31 +0530 Message-Id: <20250514122432.4019606-2-raag.jadav@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250514122432.4019606-1-raag.jadav@intel.com> References: <20250514122432.4019606-1-raag.jadav@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" With more and more drivers adopting to auxiliary bus infrastructure comes the need for managing resources at auxiliary device level. This is useful for cases where parent device shares variable number and type of resources with auxiliary child device but doesn't require any active involvement in managing them. This reduces potential duplication of resource APIs that may be required by parent device driver. With this in place parent driver will be responsible for filling up respective resources and its count in auxiliary device structure before registering it, so that the leaf drivers can utilize in their probe function. Lifecycle of these resources will be as long as the auxiliary device exists. Signed-off-by: Raag Jadav --- drivers/base/auxiliary.c | 145 ++++++++++++++++++++++++++++++++++ include/linux/auxiliary_bus.h | 18 +++++ 2 files changed, 163 insertions(+) diff --git a/drivers/base/auxiliary.c b/drivers/base/auxiliary.c index 95717d509ca9..86ae51ef50ff 100644 --- a/drivers/base/auxiliary.c +++ b/drivers/base/auxiliary.c @@ -9,6 +9,8 @@ =20 #include #include +#include +#include #include #include #include @@ -384,6 +386,149 @@ int __auxiliary_driver_register(struct auxiliary_driv= er *auxdrv, } EXPORT_SYMBOL_GPL(__auxiliary_driver_register); =20 +/** + * auxiliary_get_resource - get a resource for auxiliary device + * @auxdev: auxiliary device + * @type: resource type + * @num: resource index + * + * Return: a pointer to the resource or NULL on failure. + */ +struct resource *auxiliary_get_resource(struct auxiliary_device *auxdev, u= nsigned int type, + unsigned int num) +{ + u32 i; + + for (i =3D 0; i < auxdev->num_resources; i++) { + struct resource *r =3D &auxdev->resource[i]; + + if (type =3D=3D resource_type(r) && num-- =3D=3D 0) + return r; + } + return NULL; +} +EXPORT_SYMBOL_GPL(auxiliary_get_resource); + +#ifdef CONFIG_HAS_IOMEM +/** + * devm_auxiliary_get_and_ioremap_resource - get resource and call devm_io= remap_resource() + * for auxiliary device + * + * @auxdev: auxiliary device to use both for memory resource lookup as wel= l as + * resource management + * @index: resource index + * @res: optional output parameter to store a pointer to the obtained reso= urce. + * + * Return: a pointer to the remapped memory or an ERR_PTR() encoded error = code + * on failure. + */ +void __iomem *devm_auxiliary_get_and_ioremap_resource(struct auxiliary_dev= ice *auxdev, + unsigned int index, struct resource **res) +{ + struct resource *r; + + r =3D auxiliary_get_resource(auxdev, IORESOURCE_MEM, index); + if (res) + *res =3D r; + return devm_ioremap_resource(&auxdev->dev, r); +} +EXPORT_SYMBOL_GPL(devm_auxiliary_get_and_ioremap_resource); + +/** + * devm_auxiliary_ioremap_resource - call devm_ioremap_resource() for auxi= liary device + * + * @auxdev: auxiliary device to use both for memory resource lookup as wel= l as + * resource management + * @index: resource index + * + * Return: a pointer to the remapped memory or an ERR_PTR() encoded error = code + * on failure. + */ +void __iomem *devm_auxiliary_ioremap_resource(struct auxiliary_device *aux= dev, unsigned int index) +{ + return devm_auxiliary_get_and_ioremap_resource(auxdev, index, NULL); +} +EXPORT_SYMBOL_GPL(devm_auxiliary_ioremap_resource); +#endif + +/** + * auxiliary_get_irq_optional - get an optional IRQ for auxiliary device + * @auxdev: auxiliary device + * @num: IRQ number index + * + * Gets an IRQ for a auxiliary device. Device drivers should check the ret= urn value + * for errors so as to not pass a negative integer value to the request_ir= q() + * APIs. This is the same as auxiliary_get_irq(), except that it does not = print an + * error message if an IRQ can not be obtained. + * + * For example:: + * + * int irq =3D auxiliary_get_irq_optional(auxdev, 0); + * if (irq < 0) + * return irq; + * + * Return: non-zero IRQ number on success, negative error number on failur= e. + */ +int auxiliary_get_irq_optional(struct auxiliary_device *auxdev, unsigned i= nt num) +{ + struct resource *r; + int ret =3D -ENXIO; + + r =3D auxiliary_get_resource(auxdev, IORESOURCE_IRQ, num); + if (!r) + goto out; + + /* + * The resources may pass trigger flags to the irqs that need to be + * set up. It so happens that the trigger flags for IORESOURCE_BITS + * correspond 1-to-1 to the IRQF_TRIGGER* settings. + */ + if (r->flags & IORESOURCE_BITS) { + struct irq_data *irqd; + + irqd =3D irq_get_irq_data(r->start); + if (!irqd) + goto out; + irqd_set_trigger_type(irqd, r->flags & IORESOURCE_BITS); + } + + ret =3D r->start; + if (WARN(!ret, "0 is an invalid IRQ number\n")) + ret =3D -EINVAL; +out: + return ret; +} +EXPORT_SYMBOL_GPL(auxiliary_get_irq_optional); + +/** + * auxiliary_get_irq - get an IRQ for auxiliary device + * @auxdev: auxiliary device + * @num: IRQ number index + * + * Gets an IRQ for a auxiliary device and prints an error message if findi= ng the IRQ + * fails. Device drivers should check the return value for errors so as to= not pass + * a negative integer value to the request_irq() APIs. + * + * For example:: + * + * int irq =3D auxiliary_get_irq(auxdev, 0); + * if (irq < 0) + * return irq; + * + * Return: non-zero IRQ number on success, negative error number on failur= e. + */ +int auxiliary_get_irq(struct auxiliary_device *auxdev, unsigned int num) +{ + int ret; + + ret =3D auxiliary_get_irq_optional(auxdev, num); + if (ret < 0) + return dev_err_probe(&auxdev->dev, ret, "IRQ index %u not found\n", num); + + return ret; +} +EXPORT_SYMBOL_GPL(auxiliary_get_irq); + /** * auxiliary_driver_unregister - unregister a driver * @auxdrv: auxiliary_driver structure diff --git a/include/linux/auxiliary_bus.h b/include/linux/auxiliary_bus.h index 65dd7f154374..7d7e23313b63 100644 --- a/include/linux/auxiliary_bus.h +++ b/include/linux/auxiliary_bus.h @@ -11,6 +11,8 @@ #include #include =20 +struct resource; + /** * DOC: DEVICE_LIFESPAN * @@ -148,6 +150,8 @@ struct auxiliary_device { struct mutex lock; /* Synchronize irq sysfs creation */ bool irq_dir_exists; } sysfs; + u32 num_resources; + struct resource *resource; }; =20 /** @@ -238,6 +242,9 @@ auxiliary_device_sysfs_irq_remove(struct auxiliary_devi= ce *auxdev, int irq) {} =20 static inline void auxiliary_device_uninit(struct auxiliary_device *auxdev) { + if (auxdev->resource) + kfree(auxdev->resource); + mutex_destroy(&auxdev->sysfs.lock); put_device(&auxdev->dev); } @@ -269,4 +276,15 @@ void auxiliary_driver_unregister(struct auxiliary_driv= er *auxdrv); #define module_auxiliary_driver(__auxiliary_driver) \ module_driver(__auxiliary_driver, auxiliary_driver_register, auxiliary_dr= iver_unregister) =20 +struct resource *auxiliary_get_resource(struct auxiliary_device *auxdev, u= nsigned int type, + unsigned int num); +int auxiliary_get_irq_optional(struct auxiliary_device *auxdev, unsigned i= nt num); +int auxiliary_get_irq(struct auxiliary_device *auxdev, unsigned int num); + +#ifdef CONFIG_HAS_IOMEM +void __iomem *devm_auxiliary_get_and_ioremap_resource(struct auxiliary_dev= ice *auxdev, + unsigned int index, struct resource **res); +void __iomem *devm_auxiliary_ioremap_resource(struct auxiliary_device *aux= dev, unsigned int index); +#endif + #endif /* _AUXILIARY_BUS_H_ */ --=20 2.34.1 From nobody Sun Feb 8 04:13:12 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 25C5422A4EA for ; Wed, 14 May 2025 12:26:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.17 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747225593; cv=none; b=dOX86rStH2fveu6IkpvAP93irERE3tZQaTzFiDj1EqzxQqHfbmXayG9dTZRol/lBMKZdyH0WjyDhHzwZsLXHKogeg8l9XKzUnJlqRk3/9czAqVouuvK4PbnT0hxWqMeL95pk8SHCT5x0ggKd5hbQarmrANSvEVq54463A5mKk88= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747225593; c=relaxed/simple; bh=QM3FL+BY//hfpGJznOviWt6mq1QiVU6+56YTt5XPeTk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=nkXw22LLYFQcbGpRS3Be9B466Mx5+8Ni9lfvCe4qKW4HpB470Z7XOwt3Tryvqdmpw/OHf0zgcD1zB0jIjxHNQ+L/kOy28Nkq47PoVPgNuxYW+ynkf7IUjfSUsacMqDTlHMlYMjIiT6gaBV3XXJtE3q8RBOtCFahGxKxoI/EomGo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=iVPBBlK5; arc=none smtp.client-ip=198.175.65.17 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="iVPBBlK5" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1747225591; x=1778761591; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=QM3FL+BY//hfpGJznOviWt6mq1QiVU6+56YTt5XPeTk=; b=iVPBBlK5MiD2c5ftrN6cV1K9QicwrGFs8xhr+HbX3bT0ilRGGrQvWzDp IhNc9MLI70MLCo7jQuv+MacFJTDGGnwlFrMUIQsCm4gOusUGSEwOLq9Ei 7mWkar20lT04YDtmAh6whOAaYA+U2CP8xuy9fUkhcfdC2BQfjRfHOA6Ls Kv+bh2lmy5Y9wdnSscc0CeARjQHuI16rW6MKkfqmvr9Zk8FV4/KSU531T 2V6PjTIST88oWaISmqsyAz5cwSCcz2YxWjSUNAjYtw2J3aHVnv8ZnxTDQ oONS7liebHDtp6X2hzAdXg2IN0oH3yNAYzzLpvkDcBMVXkSyygg5DOOiN g==; X-CSE-ConnectionGUID: 59u1n/xQS0m5uNXzqCH5Ow== X-CSE-MsgGUID: tnXucWhoRAi2Ec/KL3GdjA== X-IronPort-AV: E=McAfee;i="6700,10204,11433"; a="49098856" X-IronPort-AV: E=Sophos;i="6.15,288,1739865600"; d="scan'208";a="49098856" Received: from orviesa006.jf.intel.com ([10.64.159.146]) by orvoesa109.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 May 2025 05:26:31 -0700 X-CSE-ConnectionGUID: jE/BIcWJTemMXBVFD1anYQ== X-CSE-MsgGUID: x02M7RV8S5KB14IZZg2Nnw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.15,288,1739865600"; d="scan'208";a="137946729" Received: from jraag-z790m-itx-wifi.iind.intel.com ([10.190.239.23]) by orviesa006.jf.intel.com with ESMTP; 14 May 2025 05:26:28 -0700 From: Raag Jadav To: gregkh@linuxfoundation.org, david.m.ertman@intel.com, ira.weiny@intel.com, lee@kernel.org, andriy.shevchenko@linux.intel.com, mika.westerberg@linux.intel.com, heikki.krogerus@linux.intel.com Cc: linux-kernel@vger.kernel.org, Raag Jadav Subject: [PATCH v5 2/2] mfd: core: Support auxiliary device Date: Wed, 14 May 2025 17:54:32 +0530 Message-Id: <20250514122432.4019606-3-raag.jadav@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250514122432.4019606-1-raag.jadav@intel.com> References: <20250514122432.4019606-1-raag.jadav@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend MFD subsystem to support auxiliary child device. This is useful for MFD usecases where parent device is on a discoverable bus and doesn't fit into the platform device criteria. Purpose of this implementation is to provide discoverable MFDs just enough infrastructure to register independent child devices without abusing the platform device. Current support is limited to just PCI type MFDs, but this can be further extended to support other types like USB in the future. Signed-off-by: Raag Jadav --- drivers/mfd/Kconfig | 2 +- drivers/mfd/mfd-core.c | 185 +++++++++++++++++++++++++++++---------- include/linux/mfd/core.h | 3 + 3 files changed, 142 insertions(+), 48 deletions(-) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 93773201a517..4c71a3f962c9 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -8,8 +8,8 @@ menu "Multifunction device drivers" =20 config MFD_CORE tristate + select AUXILIARY_BUS select IRQ_DOMAIN - default n =20 config MFD_CS5535 tristate "AMD CS5535 and CS5536 southbridge core functions" diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 76bd316a50af..174925bb7bf6 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -10,9 +10,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -136,10 +138,108 @@ static int mfd_match_of_node_to_dev(struct platform_= device *pdev, return 0; } =20 -static int mfd_add_device(struct device *parent, int id, - const struct mfd_cell *cell, - struct resource *mem_base, - int irq_base, struct irq_domain *domain) +static int mfd_fill_device_resources(struct device *dev, const struct mfd_= cell *cell, + struct resource *mem_base, int irq_base, + struct irq_domain *domain, struct resource *res) +{ + int r, ret; + + for (r =3D 0; r < cell->num_resources; r++) { + res[r].name =3D cell->resources[r].name; + res[r].flags =3D cell->resources[r].flags; + + /* Find out base to use */ + if ((cell->resources[r].flags & IORESOURCE_MEM) && mem_base) { + res[r].parent =3D mem_base; + res[r].start =3D mem_base->start + cell->resources[r].start; + res[r].end =3D mem_base->start + cell->resources[r].end; + } else if (cell->resources[r].flags & IORESOURCE_IRQ) { + if (domain) { + /* Unable to create mappings for IRQ ranges. */ + WARN_ON(cell->resources[r].start !=3D cell->resources[r].end); + res[r].start =3D res[r].end =3D irq_create_mapping(domain, + cell->resources[r].start); + } else { + res[r].start =3D irq_base + cell->resources[r].start; + res[r].end =3D irq_base + cell->resources[r].end; + } + } else { + res[r].parent =3D cell->resources[r].parent; + res[r].start =3D cell->resources[r].start; + res[r].end =3D cell->resources[r].end; + } + + if (!cell->ignore_resource_conflicts) { + if (has_acpi_companion(dev)) { + ret =3D acpi_check_resource_conflict(&res[r]); + if (ret) + return ret; + } + } + } + + return 0; +} + +static void mfd_release_auxiliary_device(struct device *dev) +{ + kfree(to_auxiliary_dev(dev)); +} + +static int mfd_add_auxiliary_device(struct device *parent, int id, const s= truct mfd_cell *cell, + struct resource *mem_base, int irq_base, + struct irq_domain *domain) +{ + struct auxiliary_device *auxdev; + struct resource *res; + int ret =3D -ENOMEM; + + auxdev =3D kzalloc(sizeof(*auxdev), GFP_KERNEL); + if (!auxdev) + return ret; + + res =3D kcalloc(cell->num_resources, sizeof(*res), GFP_KERNEL); + if (!res) + goto fail_alloc_res; + + auxdev->name =3D cell->name; + /* Use parent id for discoverable devices */ + auxdev->id =3D dev_is_pci(parent) ? pci_dev_id(to_pci_dev(parent)) : cell= ->id; + + auxdev->dev.parent =3D parent; + auxdev->dev.type =3D &mfd_dev_type; + auxdev->dev.release =3D mfd_release_auxiliary_device; + + ret =3D auxiliary_device_init(auxdev); + if (ret) + goto fail_aux_init; + + ret =3D mfd_fill_device_resources(&auxdev->dev, cell, mem_base, irq_base,= domain, res); + if (ret) + goto fail_aux_add; + + auxdev->resource =3D res; + auxdev->num_resources =3D cell->num_resources; + + ret =3D __auxiliary_device_add(auxdev, parent->driver->name); + if (ret) + goto fail_aux_add; + + return 0; + +fail_aux_add: + /* auxdev will be freed with the put_device() and .release sequence */ + auxiliary_device_uninit(auxdev); +fail_aux_init: + kfree(res); +fail_alloc_res: + kfree(auxdev); + return ret; +} + +static int mfd_add_platform_device(struct device *parent, int id, const st= ruct mfd_cell *cell, + struct resource *mem_base, int irq_base, + struct irq_domain *domain) { struct resource *res; struct platform_device *pdev; @@ -148,7 +248,6 @@ static int mfd_add_device(struct device *parent, int id, bool disabled =3D false; int ret =3D -ENOMEM; int platform_id; - int r; =20 if (id =3D=3D PLATFORM_DEVID_AUTO) platform_id =3D id; @@ -227,44 +326,9 @@ static int mfd_add_device(struct device *parent, int i= d, goto fail_of_entry; } =20 - for (r =3D 0; r < cell->num_resources; r++) { - res[r].name =3D cell->resources[r].name; - res[r].flags =3D cell->resources[r].flags; - - /* Find out base to use */ - if ((cell->resources[r].flags & IORESOURCE_MEM) && mem_base) { - res[r].parent =3D mem_base; - res[r].start =3D mem_base->start + - cell->resources[r].start; - res[r].end =3D mem_base->start + - cell->resources[r].end; - } else if (cell->resources[r].flags & IORESOURCE_IRQ) { - if (domain) { - /* Unable to create mappings for IRQ ranges. */ - WARN_ON(cell->resources[r].start !=3D - cell->resources[r].end); - res[r].start =3D res[r].end =3D irq_create_mapping( - domain, cell->resources[r].start); - } else { - res[r].start =3D irq_base + - cell->resources[r].start; - res[r].end =3D irq_base + - cell->resources[r].end; - } - } else { - res[r].parent =3D cell->resources[r].parent; - res[r].start =3D cell->resources[r].start; - res[r].end =3D cell->resources[r].end; - } - - if (!cell->ignore_resource_conflicts) { - if (has_acpi_companion(&pdev->dev)) { - ret =3D acpi_check_resource_conflict(&res[r]); - if (ret) - goto fail_res_conflict; - } - } - } + ret =3D mfd_fill_device_resources(&pdev->dev, cell, mem_base, irq_base, d= omain, res); + if (ret) + goto fail_res_conflict; =20 ret =3D platform_device_add_resources(pdev, res, cell->num_resources); if (ret) @@ -302,6 +366,16 @@ static int mfd_add_device(struct device *parent, int i= d, return ret; } =20 +static int mfd_add_device(struct device *parent, int id, const struct mfd_= cell *cells, + struct resource *mem_base, int irq_base, struct irq_domain *domain) +{ + /* TODO: Convert platform device abusers and remove this flag */ + if (dev_is_pci(parent) && id =3D=3D MAUX_TYPE) + return mfd_add_auxiliary_device(parent, id, cells, mem_base, irq_base, d= omain); + + return mfd_add_platform_device(parent, id, cells, mem_base, irq_base, dom= ain); +} + /** * mfd_add_devices - register child devices * @@ -340,16 +414,22 @@ int mfd_add_devices(struct device *parent, int id, } EXPORT_SYMBOL(mfd_add_devices); =20 -static int mfd_remove_devices_fn(struct device *dev, void *data) +static int mfd_remove_auxiliary_device(struct device *dev, void *data) +{ + struct auxiliary_device *auxdev =3D to_auxiliary_dev(dev); + + auxiliary_device_delete(auxdev); + auxiliary_device_uninit(auxdev); + return 0; +} + +static int mfd_remove_platform_device(struct device *dev, void *data) { struct platform_device *pdev; const struct mfd_cell *cell; struct mfd_of_node_entry *of_entry, *tmp; int *level =3D data; =20 - if (dev->type !=3D &mfd_dev_type) - return 0; - pdev =3D to_platform_device(dev); cell =3D mfd_get_cell(pdev); =20 @@ -372,6 +452,17 @@ static int mfd_remove_devices_fn(struct device *dev, v= oid *data) return 0; } =20 +static int mfd_remove_devices_fn(struct device *dev, void *data) +{ + if (dev->type !=3D &mfd_dev_type) + return 0; + + if (dev_is_platform(dev)) + return mfd_remove_platform_device(dev, data); + + return mfd_remove_auxiliary_device(dev, data); +} + void mfd_remove_devices_late(struct device *parent) { int level =3D MFD_DEP_LEVEL_HIGH; diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h index faeea7abd688..85ca273b3873 100644 --- a/include/linux/mfd/core.h +++ b/include/linux/mfd/core.h @@ -12,6 +12,9 @@ =20 #include =20 +/* TODO: Convert platform device abusers and remove this flag */ +#define MAUX_TYPE INT_MIN + #define MFD_RES_SIZE(arr) (sizeof(arr) / sizeof(struct resource)) =20 #define MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, _compat, _of_reg, = _use_of_reg, _match) \ --=20 2.34.1