Skip to content

Commit 1401c1f

Browse files
committed
NOT-FOR-UPSTREAM: PCI: apple: Use up to 4 "reset-gpios"
This brings both ASM3142 PCIe xHCI and the Wlan/BT controller in the Mac Pro (M2 Ultra, 2023) online. Handle the device reset-gpios as auxiliary ones until this can be replaced once "PCI/pwrctrl: Allow pwrctrl framework to control PERST# GPIO if available" [1] is upstream. 1: https://lore.kernel.org/linux-pci/20250707-pci-pwrctrl-perst-v1-0-c3c7e513e312@kernel.org/ Signed-off-by: Janne Grunau <j@jannau.net>
1 parent f116df0 commit 1401c1f

1 file changed

Lines changed: 23 additions & 0 deletions

File tree

drivers/pci/controller/pcie-apple.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,9 @@ static int apple_pcie_setup_link(struct apple_pcie *pcie,
558558
struct apple_pcie_port *port,
559559
struct device_node *np)
560560
{
561+
#define MAX_AUX_PERST 3
562+
struct gpio_desc *aux_reset[MAX_AUX_PERST] = { NULL };
563+
u32 num_aux_resets = 0;
561564
struct gpio_desc *reset, *pwren = NULL;
562565
u32 stat;
563566
int ret;
@@ -572,6 +575,22 @@ static int apple_pcie_setup_link(struct apple_pcie *pcie,
572575
GPIOD_OUT_HIGH, "PERST#");
573576
if (IS_ERR(reset))
574577
return PTR_ERR(reset);
578+
// HACK: use additional "reset-gpios" until pci-pwrctrl gains PERST# support.
579+
for (u32 idx = 0; idx < MAX_AUX_PERST; idx++) {
580+
aux_reset[idx] = devm_fwnode_gpiod_get_index(pcie->dev,
581+
of_fwnode_handle(np),
582+
"reset", idx + 1,
583+
GPIOD_OUT_HIGH,
584+
"PERST#");
585+
if (IS_ERR(aux_reset[idx])) {
586+
if (PTR_ERR(aux_reset[idx]) == -ENOENT)
587+
break;
588+
else
589+
return PTR_ERR(aux_reset[idx]);
590+
}
591+
num_aux_resets++;
592+
}
593+
dev_info(pcie->dev, "Using %u auxiliary PERST#\n", num_aux_resets);
575594

576595
pwren = devm_fwnode_gpiod_get(pcie->dev, of_fwnode_handle(np), "pwren",
577596
GPIOD_ASIS, "PWREN");
@@ -586,6 +605,8 @@ static int apple_pcie_setup_link(struct apple_pcie *pcie,
586605

587606
/* Assert PERST# before setting up the clock */
588607
gpiod_set_value_cansleep(reset, 1);
608+
for (u32 idx = 0; idx < num_aux_resets; idx++)
609+
gpiod_set_value_cansleep(aux_reset[idx], 1);
589610

590611
/* Power on the device if required */
591612
gpiod_set_value_cansleep(pwren, 1);
@@ -606,6 +627,8 @@ static int apple_pcie_setup_link(struct apple_pcie *pcie,
606627
/* Deassert PERST# */
607628
rmw_set(PORT_PERST_OFF, port->base + pcie->hw->port_perst);
608629
gpiod_set_value_cansleep(reset, 0);
630+
for (u32 idx = 0; idx < num_aux_resets; idx++)
631+
gpiod_set_value_cansleep(aux_reset[idx], 0);
609632

610633
/* Wait for 100ms after PERST# deassertion (PCIe r5.0, 6.6.1) */
611634
msleep(100);

0 commit comments

Comments
 (0)