From: Francesco Dolcini <[email protected]> On Apalis iMX8 the second PCIe controller only connects to the on-module Wi-Fi, which is assembled on the WB variants only. With the HSIO configuration "pciea-pcieb-sata", a probed PCIe B without a link partner keeps its PHY lane and PHYX2_PCLK1 running, and SATA then fails on the non-WB variants:
ata1.00: failed to IDENTIFY (I/O error, err_mask=0x40) The Apalis iMX8 with Wi-Fi has a 10k pull-down connected to PCIE_CTRL1_PERST_B, use it to detect the variant. Without Wi-Fi the pad is floating, and with the internal pull disabled its capacitance keeps the level it was last driven to. Drive the pad high, release it and read it back: the pull-down brings it low on the Wi-Fi variants, while it stays high when Wi-Fi is not populated. In that case, disable the PCIe B node in the kernel device tree. Tested-by: Stefan Eichenberger <[email protected]> Signed-off-by: Stefan Eichenberger <[email protected]> Signed-off-by: Francesco Dolcini <[email protected]> --- board/toradex/apalis-imx8/apalis-imx8.c | 55 +++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/board/toradex/apalis-imx8/apalis-imx8.c b/board/toradex/apalis-imx8/apalis-imx8.c index ec30ceb3a68..ba0e05a5e39 100644 --- a/board/toradex/apalis-imx8/apalis-imx8.c +++ b/board/toradex/apalis-imx8/apalis-imx8.c @@ -17,6 +17,7 @@ #include <command.h> #include <env.h> #include <errno.h> +#include <fdt_support.h> #include <linux/bitops.h> #include <linux/delay.h> #include <linux/libfdt.h> @@ -43,6 +44,14 @@ (SC_PAD_28FDSOI_PS_PD << PADRING_PULL_SHIFT) | \ (SC_PAD_28FDSOI_DSE_DV_HIGH << PADRING_DSE_SHIFT)) +#define WIFI_DETECT_PAD_CTRL ((SC_PAD_CONFIG_NORMAL << PADRING_CONFIG_SHIFT) | \ + (SC_PAD_ISO_OFF << PADRING_LPCONFIG_SHIFT) | \ + (SC_PAD_28FDSOI_PS_NONE << PADRING_PULL_SHIFT) | \ + (SC_PAD_28FDSOI_DSE_DV_HIGH << PADRING_DSE_SHIFT)) + +#define PCIEB_PERST_GPIO "GPIO5_0" +#define PCIEB_BASE_ADDR 0x5f010000 + #define TDX_USER_FUSE_BLOCK1_A 276 #define TDX_USER_FUSE_BLOCK1_B 277 #define TDX_USER_FUSE_BLOCK2_A 278 @@ -63,6 +72,10 @@ static iomux_cfg_t pcb_vers_default[] = { SC_P_MIPI_DSI0_GPIO0_01 | MUX_MODE_ALT(3) | MUX_PAD_CTRL(PCB_VERS_DEFAULT), }; +static iomux_cfg_t wifi_detect_pads[] = { + SC_P_PCIE_CTRL1_PERST_B | MUX_MODE_ALT(3) | MUX_PAD_CTRL(WIFI_DETECT_PAD_CTRL), +}; + static iomux_cfg_t uart1_pads[] = { SC_P_UART1_RX | MUX_PAD_CTRL(UART_PAD_CTRL), SC_P_UART1_TX | MUX_PAD_CTRL(UART_PAD_CTRL), @@ -290,9 +303,51 @@ void reset_cpu(void) } while (1); } +/* + * The on-module Wi-Fi is assembled only on the WB variants, together with + * the 10k pull-down on PCIE_CTRL1_PERST_B, a module input the module never + * drives. On the other variants the pad is unconnected. The pad is driven + * high, released and read right away: an unconnected pad keeps its charge + * (leakage is below 1 uA), with the pull-down it is low within + * nanoseconds. + */ +static bool apalis_imx8_has_wifi(void) +{ + struct gpio_desc perst; + int val; + + if (dm_gpio_lookup_name(PCIEB_PERST_GPIO, &perst)) + return true; + + if (dm_gpio_request(&perst, "Wi-Fi detection on PCIE_CTRL1_PERST_B")) + return true; + + imx8_iomux_setup_multiple_pads(wifi_detect_pads, + ARRAY_SIZE(wifi_detect_pads)); + + dm_gpio_set_dir_flags(&perst, GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); + udelay(10); + dm_gpio_set_dir_flags(&perst, GPIOD_IS_IN); + udelay(2); + val = dm_gpio_get_value(&perst); + + dm_gpio_free(perst.dev, &perst); + + return val != 1; +} + #if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) int ft_board_setup(void *blob, struct bd_info *bd) { + int off; + + if (!apalis_imx8_has_wifi()) { + off = fdt_node_offset_by_compat_reg(blob, "fsl,imx8q-pcie", + PCIEB_BASE_ADDR); + if (off >= 0) + fdt_status_disabled(blob, off); + } + return ft_common_board_setup(blob, bd); } #endif -- 2.56.0
