mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
usb: xhci-pci: add AMD Promontory 21 PCI glue
AMD Promontory 21 (PROM21) xHCI PCI functions use the common xhci-pci core for USB operation, but also expose controller-specific sensor data. Add a small PROM21 PCI glue driver for AMD 1022:43fc and 1022:43fd controllers. The glue delegates USB host operation to the common xhci-pci core and publishes a "hwmon" auxiliary device with parent-provided MMIO data. Auxiliary device creation failure is logged but does not fail the xHCI probe. Make the PROM21 glue a hidden Kconfig tristate driven by the user-visible SENSORS_PROM21_XHCI option. If sensor support is disabled, generic xhci-pci binds PROM21 controllers normally. If sensor support is enabled, the glue follows USB_XHCI_PCI. This keeps the auxiliary device available for a modular sensor driver while avoiding a built-in xhci-pci core handing PROM21 controllers to a glue driver that is only available as a module during initramfs. Assisted-by: Codex:gpt-5.5 Signed-off-by: Jihong Min <hurryman2212@gmail.com> Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org> Tested-by: Yaroslav Isakov <yaroslav.isakov@gmail.com> Acked-by: Guenter Roeck <linux@roeck-us.net> Link: https://patch.msgid.link/20260519000732.2334711-2-hurryman2212@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
1414b2242c
commit
9e896b4a48
|
|
@ -42,6 +42,12 @@ config USB_XHCI_PCI
|
|||
depends on USB_PCI
|
||||
default y
|
||||
|
||||
config USB_XHCI_PCI_PROM21
|
||||
tristate
|
||||
depends on USB_XHCI_PCI
|
||||
default USB_XHCI_PCI if SENSORS_PROM21_XHCI != n
|
||||
select AUXILIARY_BUS
|
||||
|
||||
config USB_XHCI_PCI_RENESAS
|
||||
tristate "Support for additional Renesas xHCI controller with firmware"
|
||||
depends on USB_XHCI_PCI
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o
|
|||
obj-$(CONFIG_USB_FHCI_HCD) += fhci.o
|
||||
obj-$(CONFIG_USB_XHCI_HCD) += xhci-hcd.o
|
||||
obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o
|
||||
obj-$(CONFIG_USB_XHCI_PCI_PROM21) += xhci-pci-prom21.o
|
||||
obj-$(CONFIG_USB_XHCI_PCI_RENESAS) += xhci-pci-renesas.o
|
||||
obj-$(CONFIG_USB_XHCI_PLATFORM) += xhci-plat-hcd.o
|
||||
obj-$(CONFIG_USB_XHCI_HISTB) += xhci-histb.o
|
||||
|
|
|
|||
137
drivers/usb/host/xhci-pci-prom21.c
Normal file
137
drivers/usb/host/xhci-pci-prom21.c
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* AMD Promontory 21 xHCI host controller PCI Bus Glue.
|
||||
*
|
||||
* This does not add any PROM21-specific USB or xHCI operation. It exists only
|
||||
* to publish an auxiliary device for integrated temperature sensor support.
|
||||
*
|
||||
* Copyright (C) 2026 Jihong Min <hurryman2212@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/auxiliary_bus.h>
|
||||
#include <linux/device/devres.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/platform_data/usb-xhci-prom21.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/hcd.h>
|
||||
|
||||
#include "xhci-pci.h"
|
||||
|
||||
struct prom21_xhci_auxdev {
|
||||
struct auxiliary_device *auxdev;
|
||||
struct prom21_xhci_pdata pdata;
|
||||
int id;
|
||||
};
|
||||
|
||||
static DEFINE_IDA(prom21_xhci_auxdev_ida);
|
||||
|
||||
static void prom21_xhci_auxdev_release(struct device *dev, void *res)
|
||||
{
|
||||
struct prom21_xhci_auxdev *prom21_auxdev = res;
|
||||
|
||||
auxiliary_device_destroy(prom21_auxdev->auxdev);
|
||||
ida_free(&prom21_xhci_auxdev_ida, prom21_auxdev->id);
|
||||
}
|
||||
|
||||
static int prom21_xhci_create_auxdev(struct pci_dev *pdev)
|
||||
{
|
||||
struct prom21_xhci_auxdev *prom21_auxdev;
|
||||
struct usb_hcd *hcd = pci_get_drvdata(pdev);
|
||||
int ret;
|
||||
|
||||
prom21_auxdev = devres_alloc(prom21_xhci_auxdev_release,
|
||||
sizeof(*prom21_auxdev), GFP_KERNEL);
|
||||
if (!prom21_auxdev)
|
||||
return -ENOMEM;
|
||||
|
||||
prom21_auxdev->pdata.pdev = pdev;
|
||||
prom21_auxdev->pdata.regs = hcd->regs;
|
||||
prom21_auxdev->pdata.rsrc_len = hcd->rsrc_len;
|
||||
|
||||
prom21_auxdev->id = ida_alloc(&prom21_xhci_auxdev_ida, GFP_KERNEL);
|
||||
if (prom21_auxdev->id < 0) {
|
||||
ret = prom21_auxdev->id;
|
||||
goto err_free_devres;
|
||||
}
|
||||
|
||||
prom21_auxdev->auxdev = auxiliary_device_create(&pdev->dev,
|
||||
KBUILD_MODNAME, "hwmon",
|
||||
&prom21_auxdev->pdata,
|
||||
prom21_auxdev->id);
|
||||
if (!prom21_auxdev->auxdev) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_ida;
|
||||
}
|
||||
|
||||
devres_add(&pdev->dev, prom21_auxdev);
|
||||
return 0;
|
||||
|
||||
err_free_ida:
|
||||
ida_free(&prom21_xhci_auxdev_ida, prom21_auxdev->id);
|
||||
err_free_devres:
|
||||
devres_free(prom21_auxdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void prom21_xhci_destroy_auxdev(struct pci_dev *pdev)
|
||||
{
|
||||
devres_release(&pdev->dev, prom21_xhci_auxdev_release, NULL, NULL);
|
||||
}
|
||||
|
||||
static int prom21_xhci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = xhci_pci_common_probe(dev, id);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
retval = prom21_xhci_create_auxdev(dev);
|
||||
if (retval) {
|
||||
/*
|
||||
* The auxiliary device only provides optional temperature sensor
|
||||
* support. Keep the xHCI controller usable if it fails.
|
||||
*/
|
||||
dev_err(&dev->dev,
|
||||
"failed to create PROM21 hwmon auxiliary device: %d\n",
|
||||
retval);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void prom21_xhci_remove(struct pci_dev *dev)
|
||||
{
|
||||
prom21_xhci_destroy_auxdev(dev);
|
||||
xhci_pci_remove(dev);
|
||||
}
|
||||
|
||||
static const struct pci_device_id pci_ids[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_PROM21_XHCI_43FC) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_PROM21_XHCI_43FD) },
|
||||
{ /* end: all zeroes */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, pci_ids);
|
||||
|
||||
static struct pci_driver prom21_xhci_driver = {
|
||||
.name = "xhci-pci-prom21",
|
||||
.id_table = pci_ids,
|
||||
|
||||
.probe = prom21_xhci_probe,
|
||||
.remove = prom21_xhci_remove,
|
||||
|
||||
.shutdown = usb_hcd_pci_shutdown,
|
||||
.driver = {
|
||||
.pm = pm_ptr(&usb_hcd_pci_pm_ops),
|
||||
},
|
||||
};
|
||||
module_pci_driver(prom21_xhci_driver);
|
||||
|
||||
MODULE_AUTHOR("Jihong Min <hurryman2212@gmail.com>");
|
||||
MODULE_DESCRIPTION("AMD Promontory 21 xHCI PCI Host Controller Driver");
|
||||
MODULE_IMPORT_NS("xhci");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -696,12 +696,23 @@ static const struct pci_device_id pci_ids_renesas[] = {
|
|||
{ /* end: all zeroes */ }
|
||||
};
|
||||
|
||||
/* handled by xhci-pci-prom21 if enabled */
|
||||
static const struct pci_device_id pci_ids_prom21[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_PROM21_XHCI_43FC) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_PROM21_XHCI_43FD) },
|
||||
{ /* end: all zeroes */ }
|
||||
};
|
||||
|
||||
static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_USB_XHCI_PCI_RENESAS) &&
|
||||
pci_match_id(pci_ids_renesas, dev))
|
||||
return -ENODEV;
|
||||
|
||||
if (IS_ENABLED(CONFIG_USB_XHCI_PCI_PROM21) &&
|
||||
pci_match_id(pci_ids_prom21, dev))
|
||||
return -ENODEV;
|
||||
|
||||
return xhci_pci_common_probe(dev, id);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@
|
|||
#ifndef XHCI_PCI_H
|
||||
#define XHCI_PCI_H
|
||||
|
||||
#define PCI_DEVICE_ID_AMD_PROM21_XHCI_43FC 0x43fc
|
||||
#define PCI_DEVICE_ID_AMD_PROM21_XHCI_43FD 0x43fd
|
||||
|
||||
int xhci_pci_common_probe(struct pci_dev *dev, const struct pci_device_id *id);
|
||||
void xhci_pci_remove(struct pci_dev *dev);
|
||||
|
||||
|
|
|
|||
22
include/linux/platform_data/usb-xhci-prom21.h
Normal file
22
include/linux/platform_data/usb-xhci-prom21.h
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* AMD Promontory 21 xHCI auxiliary device platform data.
|
||||
*
|
||||
* Copyright (C) 2026 Jihong Min <hurryman2212@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_PLATFORM_DATA_USB_XHCI_PROM21_H
|
||||
#define _LINUX_PLATFORM_DATA_USB_XHCI_PROM21_H
|
||||
|
||||
#include <linux/compiler_types.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
struct pci_dev;
|
||||
|
||||
struct prom21_xhci_pdata {
|
||||
struct pci_dev *pdev;
|
||||
void __iomem *regs;
|
||||
resource_size_t rsrc_len;
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue
Block a user