From 899453891b09289c27d2afd223be42c3757d6865 Mon Sep 17 00:00:00 2001 From: kettenis Date: Sun, 13 Feb 2022 12:02:21 +0000 Subject: [PATCH] Some PCIe devices on the M1 and M1 Pro/Max need to be explicitly powered on (most notably the WiFi chip). This is done through a GPIO controlled by the SMC. Add support for this and make sure we wait for the 100ms required by the PCIe standard when we use that GPIO to turn on power. This makes sure these devices are available even if U-Boot doesn't turn them on for us. ok patrick@ --- sys/arch/arm64/dev/aplpcie.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/sys/arch/arm64/dev/aplpcie.c b/sys/arch/arm64/dev/aplpcie.c index 026fcce4f32..e64ba3ccb9a 100644 --- a/sys/arch/arm64/dev/aplpcie.c +++ b/sys/arch/arm64/dev/aplpcie.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aplpcie.c,v 1.10 2022/01/07 19:03:57 kettenis Exp $ */ +/* $OpenBSD: aplpcie.c,v 1.11 2022/02/13 12:02:21 kettenis Exp $ */ /* * Copyright (c) 2021 Mark Kettenis * @@ -381,8 +381,9 @@ void aplpcie_init_port(struct aplpcie_softc *sc, int node) { uint32_t reg[5]; + uint32_t *pwren_gpio; uint32_t *reset_gpio; - int reset_gpiolen; + int pwren_gpiolen, reset_gpiolen; uint32_t stat; int port, timo; @@ -393,6 +394,7 @@ aplpcie_init_port(struct aplpcie_softc *sc, int node) if (port >= APLPCIE_MAX_PORTS || sc->sc_port_ios[port] == 0) return; + pwren_gpiolen = OF_getproplen(node, "pwren-gpios"); reset_gpiolen = OF_getproplen(node, "reset-gpios"); if (reset_gpiolen <= 0) return; @@ -419,6 +421,16 @@ aplpcie_init_port(struct aplpcie_softc *sc, int node) gpio_controller_config_pin(reset_gpio, GPIO_CONFIG_OUTPUT); gpio_controller_set_pin(reset_gpio, 1); + /* Power up the device if necessary. */ + if (pwren_gpiolen > 0) { + pwren_gpio = malloc(pwren_gpiolen, M_TEMP, M_WAITOK); + OF_getpropintarray(node, "pwren-gpios", + pwren_gpio, pwren_gpiolen); + gpio_controller_config_pin(pwren_gpio, GPIO_CONFIG_OUTPUT); + gpio_controller_set_pin(pwren_gpio, 1); + free(pwren_gpio, M_TEMP, pwren_gpiolen); + } + /* Setup Refclk. */ RSET4(sc, PCIE_CORE_LANE_CTRL(port), PCIE_CORE_LANE_CTRL_CFGACC); RSET4(sc, PCIE_CORE_LANE_CONF(port), PCIE_CORE_LANE_CONF_REFCLK0REQ); @@ -442,9 +454,13 @@ aplpcie_init_port(struct aplpcie_softc *sc, int node) /* * PERST# must remain asserted for at least 100us after the - * reference clock becomes stable. + * reference clock becomes stable. But also has to remain + * active at least 100ms after power up. */ - delay(100); + if (pwren_gpiolen > 0) + delay(100000); + else + delay(100); /* Deassert PERST#. */ PSET4(sc, port, PCIE_PORT_PERST, PCIE_PORT_PERST_DIS); -- 2.20.1