mb/google/zork: Add support for WiFi power sequencing
This change replaces variant_wifi_romstage_gpio_table() with
variant_pcie_power_reset_configure() to handle the reset and power
sequencing for WiFi devices pre- and post- v3 version of schematics.
These are the requirements that need to be satisfied:
1. As per PCI Express M.2 Specification Revision 3.0,
Version 1.2, Section 3.1.4 "Power-up Timing", PERST# should stay
disabled until `TPVPGL` time duration after device power has
stabilized. Value of TPVPGL is implementation specific.
2. For Intel WiFi chip, it is known to get into a bad state if the
above requirement is violated and hence requires a power cycle.
3. On pre-v3 schematics:
- For both dalboz and trembyle references, GPIO42 drives
WIFI_AUX_RESET_L which is pulled up to PP3300_WIFI.
- For both dalboz and trembyle references, PP3300_WIFI is controlled
using GPIO29. This pad gets pulled high by default on PWRGOOD
because of internal pull-up. But, at RESET# it is known to have a
glitch. When GPIO29 gets pulled high, it causes WIFI_AUX_RESET_L to
be pulled high as well. This violates the PCIe power sequencing
requirements. Hence, for pre-v3 schematics on both dalboz and
trembyle, following sequence needs to be followed:
a. Assert WIFI_AUX_RESET_L.
b. Disable power to WiFi.
c. Wait 10ms to allow WiFi power to go low.
d. Enable power to WiFi.
e. Wait 50ms as per PCIe specification.
f. Deassert WIFI_AUX_RESET_L.
4. On v3 schematics:
- For trembyle: WIFI_AUX_RESET_L is driven by GPIO86 which has an
internal PU as well as an external PU to PP3300_WIFI.
- For dalboz: WIFI_AUX_RESET is driven by GPIO29. This is active
high and has an internal PU. It also has an external 1K PD to
overcome internal PU.
- For both dalboz and trembyle references, PP3300_WIFI is
controlled by GPIO42 which has an internal PU and external
PD. Trembyle schematics have a comment saying strong PD of 2.2K but
the stuffed resistor is a weak one (499K). ON dalboz, it uses a
weak PD (which doesn't look correct and instead should be a strong
PD just like trembyle). Having a strong PD ensures that the WiFi
power is kept disabled when coming out of G3 until coreboot
configures GPIO42 as high.
- Thus, for v3 schematics, following sequence needs to be followed:
a. Assert WIFI_AUX_RESET{_L} signal.
b. Enable power to WiFi.
c. Wait 50ms as per PCIe specification.
d. Deassert WIFI_AUX_RESET{_L} signal.
BUG=b:157686402, b:158257076
TEST=Verified that QCA and AX200 cards both continue working. Tested
QCA on Dalboz and Trembyle. Tested AX200 on morphius.
Signed-off-by: Furquan Shaikh <furquan@google.com>
Change-Id: I532131ee911d5efb5130d8710f3e01578f6c9627
Reviewed-on: https://review.coreboot.org/c/coreboot/+/42738
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
462f3ed111
commit
8302585c15
8 changed files with 123 additions and 134 deletions
|
|
@ -20,8 +20,7 @@ void mainboard_romstage_entry_s3(int s3_resume)
|
|||
|
||||
gpios = variant_romstage_gpio_table(&num_gpios);
|
||||
program_gpios(gpios, num_gpios);
|
||||
gpios = variant_wifi_romstage_gpio_table(&num_gpios);
|
||||
program_gpios(gpios, num_gpios);
|
||||
variant_pcie_power_reset_configure();
|
||||
|
||||
mainboard_ec_init();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include <baseboard/variants.h>
|
||||
#include <delay.h>
|
||||
#include <gpio.h>
|
||||
#include <soc/gpio.h>
|
||||
#include <soc/smi.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -20,8 +22,6 @@ static const struct soc_amd_gpio gpio_set_stage_rom_pre_v3[] = {
|
|||
PAD_NF(GPIO_27, PCIE_RST1_L, PULL_NONE),
|
||||
/* NVME_AUX_RESET_L */
|
||||
PAD_GPO(GPIO_40, HIGH),
|
||||
/* WIFI_AUX_RESET_L */
|
||||
PAD_GPO(GPIO_42, HIGH),
|
||||
/* EN_PWR_TOUCHPAD_PS2 - reset */
|
||||
PAD_GPO(GPIO_67, LOW),
|
||||
/* EMMC_RESET - reset (default stuffing unused)*/
|
||||
|
|
@ -44,11 +44,6 @@ static const struct soc_amd_gpio gpio_set_stage_rom_pre_v3[] = {
|
|||
PAD_GPO(GPIO_142, HIGH),
|
||||
};
|
||||
|
||||
static const struct soc_amd_gpio gpio_set_wifi_pre_v3[] = {
|
||||
/* EN_PWR_WIFI */
|
||||
PAD_GPO(GPIO_29, HIGH),
|
||||
};
|
||||
|
||||
static const struct soc_amd_gpio gpio_set_stage_rom_v3[] = {
|
||||
/* PEN_POWER_EN - reset */
|
||||
PAD_GPO(GPIO_5, LOW),
|
||||
|
|
@ -62,8 +57,6 @@ static const struct soc_amd_gpio gpio_set_stage_rom_v3[] = {
|
|||
PAD_NF(GPIO_26, PCIE_RST_L, PULL_NONE),
|
||||
/* PCIE_RST1_L - Variable timings (May remove) */
|
||||
PAD_NF(GPIO_27, PCIE_RST1_L, PULL_NONE),
|
||||
/* WIFI_AUX_RESET */
|
||||
PAD_GPO(GPIO_29, LOW),
|
||||
/* NVME_AUX_RESET_L */
|
||||
PAD_GPO(GPIO_40, HIGH),
|
||||
/* EMMC_RESET - reset (default stuffing unused)*/
|
||||
|
|
@ -86,11 +79,6 @@ static const struct soc_amd_gpio gpio_set_stage_rom_v3[] = {
|
|||
PAD_GPO(GPIO_142, HIGH),
|
||||
};
|
||||
|
||||
static const struct soc_amd_gpio gpio_set_wifi_v3[] = {
|
||||
/* EN_PWR_WIFI */
|
||||
PAD_GPO(GPIO_42, HIGH),
|
||||
};
|
||||
|
||||
static const struct soc_amd_gpio gpio_set_stage_ram[] = {
|
||||
|
||||
/* PWR_BTN_L */
|
||||
|
|
@ -218,21 +206,6 @@ struct soc_amd_gpio *variant_romstage_gpio_table(size_t *size)
|
|||
return gpio_set_stage_rom_pre_v3;
|
||||
}
|
||||
|
||||
const __weak
|
||||
struct soc_amd_gpio *variant_wifi_romstage_gpio_table(size_t *size)
|
||||
{
|
||||
uint32_t board_version;
|
||||
|
||||
if (!google_chromeec_cbi_get_board_version(&board_version) &&
|
||||
(board_version >= CONFIG_VARIANT_MIN_BOARD_ID_V3_SCHEMATICS)) {
|
||||
*size = ARRAY_SIZE(gpio_set_wifi_v3);
|
||||
return gpio_set_wifi_v3;
|
||||
}
|
||||
|
||||
*size = ARRAY_SIZE(gpio_set_wifi_pre_v3);
|
||||
return gpio_set_wifi_pre_v3;
|
||||
}
|
||||
|
||||
const __weak
|
||||
struct soc_amd_gpio *variant_base_gpio_table(size_t *size)
|
||||
{
|
||||
|
|
@ -251,3 +224,61 @@ const __weak struct sci_source *get_gpe_table(size_t *num)
|
|||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void wifi_power_reset_configure_v3(void)
|
||||
{
|
||||
/*
|
||||
* Configure WiFi GPIOs such that:
|
||||
* - WIFI_AUX_RESET is configured first to assert PERST# to WiFi device.
|
||||
* - Enable power to WiFi using EN_PWR_WIFI.
|
||||
* - Wait for 50ms after power to WiFi is enabled.
|
||||
* - Deassert PERST# to WiFi device by driving WIFI_AUX_RESET low.
|
||||
*/
|
||||
static const struct soc_amd_gpio v3_wifi_table[] = {
|
||||
/* WIFI_AUX_RESET */
|
||||
PAD_GPO(GPIO_29, HIGH),
|
||||
/* EN_PWR_WIFI */
|
||||
PAD_GPO(GPIO_42, HIGH),
|
||||
};
|
||||
program_gpios(v3_wifi_table, ARRAY_SIZE(v3_wifi_table));
|
||||
|
||||
mdelay(50);
|
||||
gpio_set(GPIO_29, 0);
|
||||
}
|
||||
|
||||
static void wifi_power_reset_configure_pre_v3(void)
|
||||
{
|
||||
/*
|
||||
* Configure WiFi GPIOs such that:
|
||||
* - WIFI_AUX_RESET_L is configured first to assert PERST# to WiFi device.
|
||||
* - Disable power to WiFi since GPIO_29 goes high on PWRGOOD but has a glitch on RESET#
|
||||
* deassertion causing WiFi to enter a bad state.
|
||||
* - Wait 10ms for WiFi power to go low.
|
||||
* - Enable power to WiFi using EN_PWR_WIFI.
|
||||
* - Wait for 50ms after power to WiFi is enabled.
|
||||
* - Deassert WIFI_AUX_RESET_L.
|
||||
*/
|
||||
static const struct soc_amd_gpio pre_v3_wifi_table[] = {
|
||||
/* WIFI_AUX_RESET_L */
|
||||
PAD_GPO(GPIO_42, LOW),
|
||||
/* EN_PWR_WIFI */
|
||||
PAD_GPO(GPIO_29, LOW),
|
||||
};
|
||||
program_gpios(pre_v3_wifi_table, ARRAY_SIZE(pre_v3_wifi_table));
|
||||
|
||||
mdelay(10);
|
||||
gpio_set(GPIO_29, 1);
|
||||
mdelay(50);
|
||||
gpio_set(GPIO_42, 1);
|
||||
}
|
||||
|
||||
__weak void variant_pcie_power_reset_configure(void)
|
||||
{
|
||||
uint32_t board_version;
|
||||
|
||||
if (!google_chromeec_cbi_get_board_version(&board_version) &&
|
||||
(board_version >= CONFIG_VARIANT_MIN_BOARD_ID_V3_SCHEMATICS))
|
||||
wifi_power_reset_configure_v3();
|
||||
else
|
||||
wifi_power_reset_configure_pre_v3();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include <baseboard/variants.h>
|
||||
#include <delay.h>
|
||||
#include <gpio.h>
|
||||
#include <soc/gpio.h>
|
||||
#include <soc/smi.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -20,8 +22,6 @@ static const struct soc_amd_gpio gpio_set_stage_rom_pre_v3[] = {
|
|||
PAD_NF(GPIO_27, PCIE_RST1_L, PULL_NONE),
|
||||
/* NVME_AUX_RESET_L */
|
||||
PAD_GPO(GPIO_40, HIGH),
|
||||
/* WIFI_AUX_RESET_L */
|
||||
PAD_GPO(GPIO_42, HIGH),
|
||||
/* EN_PWR_TOUCHPAD_PS2 - reset */
|
||||
PAD_GPO(GPIO_67, LOW),
|
||||
/* EMMC_RESET - reset (default stuffing unused)*/
|
||||
|
|
@ -42,11 +42,6 @@ static const struct soc_amd_gpio gpio_set_stage_rom_pre_v3[] = {
|
|||
PAD_GPO(GPIO_142, HIGH),
|
||||
};
|
||||
|
||||
static const struct soc_amd_gpio gpio_set_wifi_pre_v3[] = {
|
||||
/* EN_PWR_WIFI */
|
||||
PAD_GPO(GPIO_29, HIGH),
|
||||
};
|
||||
|
||||
static const struct soc_amd_gpio gpio_set_stage_rom_v3[] = {
|
||||
/* PEN_POWER_EN - reset */
|
||||
PAD_GPO(GPIO_5, LOW),
|
||||
|
|
@ -66,8 +61,6 @@ static const struct soc_amd_gpio gpio_set_stage_rom_v3[] = {
|
|||
PAD_GPO(GPIO_68, HIGH),
|
||||
/* EN_PWR_CAMERA - reset */
|
||||
PAD_GPO(GPIO_76, LOW),
|
||||
/* WIFI_AUX_RESET_L */
|
||||
PAD_GPO(GPIO_86, HIGH),
|
||||
/* CLK_REQ0_L - WIFI */
|
||||
PAD_NF(GPIO_92, CLK_REQ0_L, PULL_UP),
|
||||
/* CLK_REQ1_L - SD Card */
|
||||
|
|
@ -82,11 +75,6 @@ static const struct soc_amd_gpio gpio_set_stage_rom_v3[] = {
|
|||
PAD_GPO(GPIO_142, HIGH),
|
||||
};
|
||||
|
||||
static const struct soc_amd_gpio gpio_set_wifi_v3[] = {
|
||||
/* EN_PWR_WIFI */
|
||||
PAD_GPO(GPIO_42, HIGH),
|
||||
};
|
||||
|
||||
static const struct soc_amd_gpio gpio_set_stage_ram[] = {
|
||||
|
||||
/* PWR_BTN_L */
|
||||
|
|
@ -213,21 +201,6 @@ struct soc_amd_gpio *variant_romstage_gpio_table(size_t *size)
|
|||
return gpio_set_stage_rom_pre_v3;
|
||||
}
|
||||
|
||||
const __weak
|
||||
struct soc_amd_gpio *variant_wifi_romstage_gpio_table(size_t *size)
|
||||
{
|
||||
uint32_t board_version;
|
||||
|
||||
if (!google_chromeec_cbi_get_board_version(&board_version) &&
|
||||
(board_version >= CONFIG_VARIANT_MIN_BOARD_ID_V3_SCHEMATICS)) {
|
||||
*size = ARRAY_SIZE(gpio_set_wifi_v3);
|
||||
return gpio_set_wifi_v3;
|
||||
}
|
||||
|
||||
*size = ARRAY_SIZE(gpio_set_wifi_pre_v3);
|
||||
return gpio_set_wifi_pre_v3;
|
||||
}
|
||||
|
||||
const __weak
|
||||
struct soc_amd_gpio *variant_base_gpio_table(size_t *size)
|
||||
{
|
||||
|
|
@ -246,3 +219,61 @@ const __weak struct sci_source *get_gpe_table(size_t *num)
|
|||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void wifi_power_reset_configure_v3(void)
|
||||
{
|
||||
/*
|
||||
* Configure WiFi GPIOs such that:
|
||||
* - WIFI_AUX_RESET_L is configured first to assert PERST# to WiFi device.
|
||||
* - Enable power to WiFi using EN_PWR_WIFI.
|
||||
* - Wait for 50ms after power to WiFi is enabled.
|
||||
* - Deassert WIFI_AUX_RESET_L.
|
||||
*/
|
||||
static const struct soc_amd_gpio v3_wifi_table[] = {
|
||||
/* WIFI_AUX_RESET_L */
|
||||
PAD_GPO(GPIO_86, LOW),
|
||||
/* EN_PWR_WIFI */
|
||||
PAD_GPO(GPIO_42, HIGH),
|
||||
};
|
||||
program_gpios(v3_wifi_table, ARRAY_SIZE(v3_wifi_table));
|
||||
|
||||
mdelay(50);
|
||||
gpio_set(GPIO_86, 1);
|
||||
}
|
||||
|
||||
static void wifi_power_reset_configure_pre_v3(void)
|
||||
{
|
||||
/*
|
||||
* Configure WiFi GPIOs such that:
|
||||
* - WIFI_AUX_RESET_L is configured first to assert PERST# to WiFi device.
|
||||
* - Disable power to WiFi since GPIO_29 goes high on PWRGOOD but has a glitch on RESET#
|
||||
* deassertion causing WiFi to enter a bad state.
|
||||
* - Wait 10ms for WiFi power to go low.
|
||||
* - Enable power to WiFi using EN_PWR_WIFI.
|
||||
* - Wait for 50ms after power to WiFi is enabled.
|
||||
* - Deassert WIFI_AUX_RESET_L.
|
||||
*/
|
||||
static const struct soc_amd_gpio pre_v3_wifi_table[] = {
|
||||
/* WIFI_AUX_RESET_L */
|
||||
PAD_GPO(GPIO_42, LOW),
|
||||
/* EN_PWR_WIFI */
|
||||
PAD_GPO(GPIO_29, LOW),
|
||||
};
|
||||
program_gpios(pre_v3_wifi_table, ARRAY_SIZE(pre_v3_wifi_table));
|
||||
|
||||
mdelay(10);
|
||||
gpio_set(GPIO_29, 1);
|
||||
mdelay(50);
|
||||
gpio_set(GPIO_42, 1);
|
||||
}
|
||||
|
||||
__weak void variant_pcie_power_reset_configure(void)
|
||||
{
|
||||
uint32_t board_version;
|
||||
|
||||
if (!google_chromeec_cbi_get_board_version(&board_version) &&
|
||||
(board_version >= CONFIG_VARIANT_MIN_BOARD_ID_V3_SCHEMATICS))
|
||||
wifi_power_reset_configure_v3();
|
||||
else
|
||||
wifi_power_reset_configure_pre_v3();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
const struct sci_source *get_gpe_table(size_t *num);
|
||||
const struct soc_amd_gpio *variant_early_gpio_table(size_t *size);
|
||||
const struct soc_amd_gpio *variant_romstage_gpio_table(size_t *size);
|
||||
const struct soc_amd_gpio *variant_wifi_romstage_gpio_table(size_t *size);
|
||||
/*
|
||||
* This function provides base GPIO configuration table. It is typically provided by
|
||||
* baseboard using a weak implementation. If GPIO configuration for a variant differs
|
||||
|
|
@ -29,6 +28,8 @@ const struct soc_amd_gpio *variant_override_gpio_table(size_t *size);
|
|||
void variant_romstage_entry(void);
|
||||
/* Modify devictree settings during ramstage. */
|
||||
void variant_devtree_update(void);
|
||||
/* Configure PCIe power and reset lines as per variant sequencing requirements. */
|
||||
void variant_pcie_power_reset_configure(void);
|
||||
|
||||
/* Per variant FSP-S initialization, default implementation in baseboard and
|
||||
* overrideable by the variant. */
|
||||
|
|
|
|||
|
|
@ -2,6 +2,4 @@
|
|||
|
||||
subdirs-y += ./spd
|
||||
|
||||
romstage-y += ./romstage.c
|
||||
|
||||
ramstage-y += gpio.c
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <soc/romstage.h>
|
||||
#include <baseboard/variants.h>
|
||||
#include <ec/google/chromeec/ec.h>
|
||||
|
||||
#include <gpio.h>
|
||||
#include <soc/gpio.h>
|
||||
#include <variant/gpio.h>
|
||||
|
||||
void variant_romstage_entry(void)
|
||||
{
|
||||
/* Power the wifi card */
|
||||
gpio_set(EN_PWR_WIFI, 1);
|
||||
}
|
||||
|
||||
static const struct soc_amd_gpio berknip_gpio_set_wifi[] = {
|
||||
/* EN_PWR_WIFI - Power off. Pull high in romstage.c */
|
||||
PAD_GPO(GPIO_29, LOW),
|
||||
};
|
||||
|
||||
const struct soc_amd_gpio *variant_wifi_romstage_gpio_table(size_t *size)
|
||||
{
|
||||
*size = ARRAY_SIZE(berknip_gpio_set_wifi);
|
||||
return berknip_gpio_set_wifi;
|
||||
}
|
||||
|
|
@ -2,6 +2,4 @@
|
|||
|
||||
subdirs-y += ./spd
|
||||
|
||||
romstage-y += ./romstage.c
|
||||
|
||||
ramstage-y += gpio.c
|
||||
|
|
|
|||
|
|
@ -1,42 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <soc/romstage.h>
|
||||
#include <baseboard/variants.h>
|
||||
#include <ec/google/chromeec/ec.h>
|
||||
|
||||
#include <gpio.h>
|
||||
#include <soc/gpio.h>
|
||||
#include <variant/gpio.h>
|
||||
#include <delay.h>
|
||||
|
||||
void variant_romstage_entry(void)
|
||||
{
|
||||
//SET WIFI_PCIE_RESET_L HIGH
|
||||
gpio_set(WIFI_PCIE_RESET_L, 1);
|
||||
|
||||
/* Power the wifi card */
|
||||
/* wait 10ms to discharge EN_PWR_WIFI to 0V */
|
||||
mdelay(10);
|
||||
gpio_set(EN_PWR_WIFI, 1);
|
||||
|
||||
/* SET WIFI_PCIE_RESET_L LOW */
|
||||
gpio_set(WIFI_PCIE_RESET_L, 0);
|
||||
|
||||
/* Qualcomm Atheros NFA344A needs at least 10ms delay */
|
||||
mdelay(10);
|
||||
|
||||
/* SET WIFI_PCIE_RESET_L HIGH */
|
||||
gpio_set(WIFI_PCIE_RESET_L, 1);
|
||||
}
|
||||
|
||||
static const struct soc_amd_gpio morphius_gpio_set_wifi[] = {
|
||||
/* EN_PWR_WIFI - Power off. Pull high in romstage.c */
|
||||
PAD_GPO(GPIO_29, LOW),
|
||||
};
|
||||
|
||||
const struct soc_amd_gpio *variant_wifi_romstage_gpio_table(size_t *size)
|
||||
{
|
||||
*size = ARRAY_SIZE(morphius_gpio_set_wifi);
|
||||
return morphius_gpio_set_wifi;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue