esp-idf/components/esp_wifi/src/coexist.c

398 lines
13 KiB
C
Raw Normal View History

2021-09-30 03:12:55 -04:00
/*
* 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*/