esp-idf/components/esp_wifi/src/coexist.c
alex.li 9bbe6e7fa3 Support external coexist formal code for C2 & S3,
and optimize RX category in external coex.
2022-11-08 19:10:38 +05:30

398 lines
13 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_coexist.h"
#include "esp_coexist_internal.h"
#if CONFIG_EXTERNAL_COEX_ENABLE
#include "esp_log.h"
#include "driver/gpio.h"
#include "esp_rom_gpio.h"
#include "hal/gpio_hal.h"
#include "hal/gpio_types.h"
#include "soc/gpio_periph.h"
#include "soc/gpio_struct.h"
#endif
const char *esp_coex_version_get(void)
{
return coex_version_get();
}
esp_err_t esp_coex_preference_set(esp_coex_prefer_t prefer)
{
return coex_preference_set((coex_prefer_t)prefer);
}
#if CONFIG_EXTERNAL_COEX_ENABLE
#define GPIO_PIN_REG(a) (GPIO_PIN0_REG + a * 0x04)
#if SOC_EXTERNAL_COEX_ADVANCE
static const char *TAG = "external_coex";
external_coex_classification s_external_coex_partner[EXTERNAL_COEX_UNKNOWN_ROLE][EXTERN_COEX_WIRE_NUM] = {
{ wire_1_leader_mode, wire_2_leader_mode, wire_3_leader_mode },
{},
{ wire_1_follower_mode, wire_2_follower_mode, wire_3_follower_mode },
};
static esp_external_coex_advance_t g_external_coex_params = { EXTERNAL_COEX_LEADER_ROLE, 0, true };
esp_external_coex_follower_pti_t g_external_coex_follower_pti_val = { 0, 0 };
esp_err_t esp_external_coex_set_work_mode(esp_extern_coex_work_mode_t work_mode)
{
g_external_coex_params.work_mode = work_mode;
if(EXTERNAL_COEX_FOLLOWER_ROLE == work_mode) {
g_external_coex_follower_pti_val.pti_val1 = 8;
g_external_coex_follower_pti_val.pti_val2 = 13;
}
return ESP_OK;
}
esp_err_t esp_external_coex_set_grant_delay(uint8_t delay_us)
{
g_external_coex_params.delay_us = delay_us;
return ESP_OK;
}
esp_err_t esp_external_coex_set_validate_high(bool is_high_valid)
{
g_external_coex_params.is_high_valid = is_high_valid;
return ESP_OK;
}
bool is_legal_external_coex_gpio(external_coex_wire_t wire_type, esp_external_coex_gpio_set_t gpio_pin)
{
external_coex_classification external_coex_configure = s_external_coex_partner[g_external_coex_params.work_mode][wire_type];
switch (external_coex_configure)
{
case wire_3_leader_mode:
{
if(gpio_pin.in_pin0 == gpio_pin.in_pin1) {
return false;
}
if(gpio_pin.in_pin0 == gpio_pin.out_pin0) {
return false;
}
if(gpio_pin.in_pin1 == gpio_pin.out_pin0) {
return false;
}
if(gpio_pin.in_pin0 >= SOC_GPIO_PIN_COUNT) {
return false;
}
if(gpio_pin.in_pin1 >= SOC_GPIO_PIN_COUNT) {
return false;
}
if(gpio_pin.out_pin0 >= SOC_GPIO_PIN_COUNT) {
return false;
}
return true;
}
case wire_3_follower_mode:
{
if(gpio_pin.in_pin0 == gpio_pin.out_pin0) {
return false;
}
if(gpio_pin.in_pin0 == gpio_pin.out_pin1) {
return false;
}
if(gpio_pin.out_pin0 == gpio_pin.out_pin1) {
return false;
}
if(gpio_pin.in_pin0 >= SOC_GPIO_PIN_COUNT) {
return false;
}
if(gpio_pin.out_pin1 >= SOC_GPIO_PIN_COUNT) {
return false;
}
if(gpio_pin.out_pin0 >= SOC_GPIO_PIN_COUNT) {
return false;
}
return true;
}
case wire_2_leader_mode:
case wire_2_follower_mode:
{
if(gpio_pin.in_pin0 == gpio_pin.out_pin0) {
return false;
}
if(gpio_pin.in_pin0 >= SOC_GPIO_PIN_COUNT) {
return false;
}
if(gpio_pin.out_pin0 >= SOC_GPIO_PIN_COUNT) {
return false;
}
return true;
}
case wire_1_leader_mode:
{
if(gpio_pin.in_pin0 >= SOC_GPIO_PIN_COUNT) {
return false;
}
return true;
}
case wire_1_follower_mode:
{
if(gpio_pin.out_pin0 >= SOC_GPIO_PIN_COUNT) {
return false;
}
return true;
}
default:
return false;
}
}
esp_err_t esp_external_coex_leader_role_set_gpio_pin(external_coex_wire_t wire_type, uint32_t in_pin0, uint32_t in_pin1, uint32_t out_pin0)
{
esp_external_coex_set_work_mode(EXTERNAL_COEX_LEADER_ROLE);
esp_external_coex_gpio_set_t gpio_pin;
switch (wire_type) {
case EXTERN_COEX_WIRE_3:
{
gpio_pin.in_pin0 = in_pin0;
gpio_pin.in_pin1 = in_pin1;
gpio_pin.out_pin0 = out_pin0;
break;
}
case EXTERN_COEX_WIRE_2:
{
gpio_pin.in_pin0 = in_pin0;
gpio_pin.out_pin0 = out_pin0;
break;
}
case EXTERN_COEX_WIRE_1:
{
gpio_pin.in_pin0 = in_pin0;
break;
}
default:
{
gpio_pin.in_pin0 = in_pin0;
gpio_pin.in_pin1 = in_pin1;
gpio_pin.out_pin0 = out_pin0;
break;
}
}
return esp_enable_extern_coex_gpio_pin(wire_type, gpio_pin);
}
esp_err_t esp_external_coex_follower_role_set_gpio_pin(external_coex_wire_t wire_type, uint32_t in_pin0, uint32_t out_pin0, uint32_t out_pin1)
{
esp_external_coex_set_work_mode(EXTERNAL_COEX_FOLLOWER_ROLE);
esp_external_coex_gpio_set_t gpio_pin;
switch (wire_type) {
case EXTERN_COEX_WIRE_3:
{
gpio_pin.in_pin0 = in_pin0;
gpio_pin.out_pin0 = out_pin0;
gpio_pin.out_pin1 = out_pin1;
break;
}
case EXTERN_COEX_WIRE_2:
{
gpio_pin.in_pin0 = in_pin0;
gpio_pin.out_pin0 = out_pin0;
break;
}
case EXTERN_COEX_WIRE_1:
{
gpio_pin.out_pin0 = out_pin0;
break;
}
default:
{
gpio_pin.in_pin0 = in_pin0;
gpio_pin.out_pin0 = out_pin0;
gpio_pin.out_pin1 = out_pin1;
break;
}
}
return esp_enable_extern_coex_gpio_pin(wire_type, gpio_pin);
}
#endif
esp_err_t esp_enable_extern_coex_gpio_pin(external_coex_wire_t wire_type, esp_external_coex_gpio_set_t gpio_pin)
{
#if SOC_EXTERNAL_COEX_ADVANCE
if(false == is_legal_external_coex_gpio(wire_type, gpio_pin))
{
ESP_LOGE(TAG, "Configure external coex with unexpected gpio pin!!!\n");
return ESP_ERR_INVALID_ARG;
}
phy_coex_force_rx_ant();
esp_coex_external_params(g_external_coex_params, g_external_coex_follower_pti_val.pti_val1,
g_external_coex_follower_pti_val.pti_val2);
#endif
switch (wire_type)
{
case EXTERN_COEX_WIRE_3:
{
#if SOC_EXTERNAL_COEX_ADVANCE
if(EXTERNAL_COEX_LEADER_ROLE == g_external_coex_params.work_mode) {
#endif
/*Input gpio pin setup --> GPIO_BT_PRIORITY_IDXGPIO_BT_ACTIVE_IDX*/
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_pin.in_pin0], PIN_FUNC_GPIO);
gpio_set_direction(gpio_pin.in_pin0, GPIO_MODE_INPUT);
#if SOC_EXTERNAL_COEX_ADVANCE
esp_rom_gpio_connect_in_signal(gpio_pin.in_pin0, EXTERN_ACTIVE_I_IDX, false);
#else
esp_rom_gpio_connect_in_signal(gpio_pin.in_pin0, GPIO_BT_ACTIVE_IDX, false);
#endif
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_pin.in_pin1], PIN_FUNC_GPIO);
gpio_set_direction(gpio_pin.in_pin1, GPIO_MODE_INPUT);
#if SOC_EXTERNAL_COEX_ADVANCE
esp_rom_gpio_connect_in_signal(gpio_pin.in_pin1, EXTERN_PRIORITY_I_IDX, false);
#else
esp_rom_gpio_connect_in_signal(gpio_pin.in_pin1, GPIO_BT_PRIORITY_IDX, false);
#endif
/*Output gpio pin setup --> GPIO_WLAN_ACTIVE_IDX: 1 BT, 0 WiFi*/
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_pin.out_pin0], PIN_FUNC_GPIO);
gpio_set_direction(gpio_pin.out_pin0, GPIO_MODE_OUTPUT);
REG_WRITE(GPIO_ENABLE_W1TC_REG, BIT(gpio_pin.out_pin0));
#if SOC_EXTERNAL_COEX_ADVANCE
esp_rom_gpio_connect_out_signal(gpio_pin.out_pin0, EXTERN_ACTIVE_O_IDX, false, false);
#else
esp_rom_gpio_connect_out_signal(gpio_pin.out_pin0, GPIO_WLAN_ACTIVE_IDX, false, false);
#endif
REG_SET_FIELD(GPIO_PIN_REG(gpio_pin.in_pin0), GPIO_PIN1_SYNC1_BYPASS, 2);
REG_SET_FIELD(GPIO_PIN_REG(gpio_pin.in_pin0), GPIO_PIN1_SYNC2_BYPASS, 2);
REG_SET_FIELD(GPIO_PIN_REG(gpio_pin.in_pin1), GPIO_PIN1_SYNC1_BYPASS, 2);
REG_SET_FIELD(GPIO_PIN_REG(gpio_pin.in_pin1), GPIO_PIN1_SYNC2_BYPASS, 2);
#if SOC_EXTERNAL_COEX_ADVANCE
}
else if(EXTERNAL_COEX_FOLLOWER_ROLE == g_external_coex_params.work_mode) {
/*Input gpio pin setup --> GPIO_BT_PRIORITY_IDXGPIO_BT_ACTIVE_IDX*/
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_pin.in_pin0], PIN_FUNC_GPIO);
gpio_set_direction(gpio_pin.in_pin0, GPIO_MODE_INPUT);
esp_rom_gpio_connect_in_signal(gpio_pin.in_pin0, EXTERN_ACTIVE_I_IDX, false);
/*Output gpio pin setup --> GPIO_WLAN_ACTIVE_IDX: 1 BT, 0 WiFi*/
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_pin.out_pin0], PIN_FUNC_GPIO);
gpio_set_direction(gpio_pin.out_pin0, GPIO_MODE_OUTPUT);
REG_WRITE(GPIO_ENABLE_W1TC_REG, BIT(gpio_pin.out_pin0));
esp_rom_gpio_connect_out_signal(gpio_pin.out_pin0, EXTERN_ACTIVE_O_IDX, false, false);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_pin.out_pin1], PIN_FUNC_GPIO);
gpio_set_direction(gpio_pin.out_pin1, GPIO_MODE_OUTPUT);
REG_WRITE(GPIO_ENABLE_W1TC_REG, BIT(gpio_pin.out_pin1));
esp_rom_gpio_connect_out_signal(gpio_pin.out_pin1, EXTERN_PRIORITY_O_IDX, false, false);
REG_SET_FIELD(GPIO_PIN_REG(gpio_pin.in_pin0), GPIO_PIN1_SYNC1_BYPASS, 2);
REG_SET_FIELD(GPIO_PIN_REG(gpio_pin.in_pin0), GPIO_PIN1_SYNC2_BYPASS, 2);
}
#else
#endif
int ret = esp_coex_external_set(EXTERN_COEX_PTI_MID, EXTERN_COEX_PTI_MID, EXTERN_COEX_PTI_HIGH);
if (ESP_OK != ret) {
return ESP_FAIL;
}
break;
}
case EXTERN_COEX_WIRE_2:
{
/*Input gpio pin setup --> GPIO_BT_PRIORITY_IDXGPIO_BT_ACTIVE_IDX*/
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_pin.in_pin0], PIN_FUNC_GPIO);
gpio_set_direction(gpio_pin.in_pin0, GPIO_MODE_INPUT);
#if SOC_EXTERNAL_COEX_ADVANCE
esp_rom_gpio_connect_in_signal(gpio_pin.in_pin0, EXTERN_ACTIVE_I_IDX, false);
#else
esp_rom_gpio_connect_in_signal(gpio_pin.in_pin0, GPIO_BT_ACTIVE_IDX, false);
#endif
/*Output gpio pin setup --> GPIO_WLAN_ACTIVE_IDX: 1 BT, 0 WiFi*/
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_pin.out_pin0], PIN_FUNC_GPIO);
gpio_set_direction(gpio_pin.out_pin0, GPIO_MODE_OUTPUT);
REG_WRITE(GPIO_ENABLE_W1TC_REG, BIT(gpio_pin.out_pin0));
#if SOC_EXTERNAL_COEX_ADVANCE
esp_rom_gpio_connect_out_signal(gpio_pin.out_pin0, EXTERN_ACTIVE_O_IDX, false, false);
#else
esp_rom_gpio_connect_out_signal(gpio_pin.out_pin0, GPIO_WLAN_ACTIVE_IDX, false, false);
#endif
REG_SET_FIELD(GPIO_PIN_REG(gpio_pin.in_pin0), GPIO_PIN1_SYNC1_BYPASS, 2);
REG_SET_FIELD(GPIO_PIN_REG(gpio_pin.in_pin0), GPIO_PIN1_SYNC2_BYPASS, 2);
int ret = esp_coex_external_set(EXTERN_COEX_PTI_MID, EXTERN_COEX_PTI_MID, EXTERN_COEX_PTI_MID);
if (ESP_OK != ret) {
return ESP_FAIL;
}
break;
}
case EXTERN_COEX_WIRE_1:
{
#if SOC_EXTERNAL_COEX_ADVANCE
if(EXTERNAL_COEX_LEADER_ROLE == g_external_coex_params.work_mode) {
#endif
/*Input gpio pin setup --> GPIO_BT_PRIORITY_IDXGPIO_BT_ACTIVE_IDX*/
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_pin.in_pin0], PIN_FUNC_GPIO);
gpio_set_direction(gpio_pin.in_pin0, GPIO_MODE_INPUT);
#if SOC_EXTERNAL_COEX_ADVANCE
esp_rom_gpio_connect_in_signal(gpio_pin.in_pin0, EXTERN_ACTIVE_I_IDX, false);
#else
esp_rom_gpio_connect_in_signal(gpio_pin.in_pin0, GPIO_BT_ACTIVE_IDX, false);
#endif
REG_SET_FIELD(GPIO_PIN_REG(gpio_pin.in_pin0), GPIO_PIN1_SYNC1_BYPASS, 2);
REG_SET_FIELD(GPIO_PIN_REG(gpio_pin.in_pin0), GPIO_PIN1_SYNC2_BYPASS, 2);
#if SOC_EXTERNAL_COEX_ADVANCE
}
else if(EXTERNAL_COEX_FOLLOWER_ROLE == g_external_coex_params.work_mode) {
/*Output gpio pin setup --> GPIO_WLAN_ACTIVE_IDX: 1 BT, 0 WiFi*/
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_pin.out_pin0], PIN_FUNC_GPIO);
gpio_set_direction(gpio_pin.out_pin0, GPIO_MODE_OUTPUT);
REG_WRITE(GPIO_ENABLE_W1TC_REG, BIT(gpio_pin.out_pin0));
esp_rom_gpio_connect_out_signal(gpio_pin.out_pin0, EXTERN_ACTIVE_O_IDX, false, false);
}
#else
#endif
int ret = esp_coex_external_set(EXTERN_COEX_PTI_HIGH, EXTERN_COEX_PTI_HIGH, EXTERN_COEX_PTI_HIGH);
if (ESP_OK != ret) {
return ESP_FAIL;
}
break;
}
default:
{
return ESP_FAIL;
}
}
return ESP_OK;
}
esp_err_t esp_disable_extern_coex_gpio_pin()
{
#if SOC_EXTERNAL_COEX_ADVANCE
phy_coex_dismiss_rx_ant();
#endif
esp_coex_external_stop();
return ESP_OK;
}
#endif/*External Coex*/