drivers: wifi: infineon: Add SPI support to AIROC driver
Added support for SPI in 4-wire and 3-wire configurations to the Infineon AIROC WiFi driver (drivers/wifi/infineon). Review changes: Move DT_DRV_COMPAT to common header file Correct board-specific preprocessor lines Removed AIROC_MAP_COUNTRY_CODE Move Pico W configuration details to devicetree Use pinctrl to manage shared data/interrupt GPIO Clean up bus selection in Kconfig.airoc Make SDIO and SPI bus struct independent Replace LOG_DBG with LOG_ERR Remove functionally duplicate operation Remove spurious Kconfig option Minor cleanup in CMakeLists.txt Signed-off-by: Steve Boylan <stephen.boylan@beechwoods.com>
This commit is contained in:
parent
46c9d160eb
commit
37e39dee58
10 changed files with 535 additions and 124 deletions
|
@ -4,8 +4,12 @@
|
|||
|
||||
zephyr_include_directories(./)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_WIFI_AIROC airoc_wifi.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_WIFI_AIROC airoc_whd_hal.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_WIFI_AIROC
|
||||
airoc_wifi.c
|
||||
airoc_whd_hal_common.c
|
||||
)
|
||||
zephyr_library_sources_ifdef(CONFIG_AIROC_WIFI_BUS_SDIO airoc_whd_hal_sdio.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_AIROC_WIFI_BUS_SPI airoc_whd_hal_spi.c)
|
||||
|
||||
zephyr_compile_definitions(CYBSP_WIFI_CAPABLE)
|
||||
zephyr_compile_definitions(CY_RTOS_AWARE)
|
||||
|
|
|
@ -4,20 +4,37 @@
|
|||
|
||||
menuconfig WIFI_AIROC
|
||||
bool "Infineon AIROC SoC Wi-Fi support"
|
||||
depends on DT_HAS_INFINEON_AIROC_WIFI_ENABLED
|
||||
default y
|
||||
select THREAD_CUSTOM_DATA
|
||||
select WIFI_OFFLOAD
|
||||
select NET_L2_ETHERNET
|
||||
select NET_L2_WIFI_MGMT
|
||||
select SDIO_STACK
|
||||
select SDHC
|
||||
select GPIO
|
||||
select WIFI_USE_NATIVE_NETWORKING
|
||||
select USE_INFINEON_ABSTRACTION_RTOS
|
||||
depends on DT_HAS_INFINEON_AIROC_WIFI_ENABLED
|
||||
help
|
||||
Enable Infineon AIROC SoC Wi-Fi support.
|
||||
|
||||
if WIFI_AIROC
|
||||
|
||||
config AIROC_WIFI_BUS_SDIO
|
||||
bool
|
||||
default y
|
||||
depends on $(dt_compat_on_bus,$(DT_COMPAT_INFINEON_AIROC_WIFI),sd)
|
||||
select SDHC
|
||||
select SDIO_STACK
|
||||
help
|
||||
Enable SDIO bus support.
|
||||
|
||||
config AIROC_WIFI_BUS_SPI
|
||||
bool
|
||||
default y
|
||||
depends on $(dt_compat_on_bus,$(DT_COMPAT_INFINEON_AIROC_WIFI),spi)
|
||||
select SPI
|
||||
help
|
||||
Enable SPI bus support
|
||||
|
||||
config AIROC_WIFI_EVENT_TASK_STACK_SIZE
|
||||
int "Event Task Stack Size"
|
||||
default 4096
|
||||
|
|
84
drivers/wifi/infineon/airoc_whd_hal_common.c
Normal file
84
drivers/wifi/infineon/airoc_whd_hal_common.c
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or
|
||||
* an affiliate of Cypress Semiconductor Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "airoc_whd_hal_common.h"
|
||||
#include "airoc_wifi.h"
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
|
||||
LOG_MODULE_DECLARE(infineon_airoc_wifi, CONFIG_WIFI_LOG_LEVEL);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/******************************************************
|
||||
* Function
|
||||
******************************************************/
|
||||
|
||||
int airoc_wifi_power_on(const struct device *dev)
|
||||
{
|
||||
#if DT_INST_NODE_HAS_PROP(0, wifi_reg_on_gpios)
|
||||
int ret;
|
||||
const struct airoc_wifi_config *config = dev->config;
|
||||
|
||||
/* Check WIFI REG_ON gpio instance */
|
||||
if (!device_is_ready(config->wifi_reg_on_gpio.port)) {
|
||||
LOG_ERR("Error: failed to configure wifi_reg_on %s pin %d",
|
||||
config->wifi_reg_on_gpio.port->name, config->wifi_reg_on_gpio.pin);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Configure wifi_reg_on as output */
|
||||
ret = gpio_pin_configure_dt(&config->wifi_reg_on_gpio, GPIO_OUTPUT);
|
||||
if (ret) {
|
||||
LOG_ERR("Error %d: failed to configure wifi_reg_on %s pin %d", ret,
|
||||
config->wifi_reg_on_gpio.port->name, config->wifi_reg_on_gpio.pin);
|
||||
return ret;
|
||||
}
|
||||
ret = gpio_pin_set_dt(&config->wifi_reg_on_gpio, 0);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Allow CBUCK regulator to discharge */
|
||||
k_msleep(WLAN_CBUCK_DISCHARGE_MS);
|
||||
|
||||
/* WIFI power on */
|
||||
ret = gpio_pin_set_dt(&config->wifi_reg_on_gpio, 1);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
k_msleep(WLAN_POWER_UP_DELAY_MS);
|
||||
#endif /* DT_INST_NODE_HAS_PROP(0, reg_on_gpios) */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement WHD memory wrappers
|
||||
*/
|
||||
|
||||
void *whd_mem_malloc(size_t size)
|
||||
{
|
||||
return k_malloc(size);
|
||||
}
|
||||
|
||||
void *whd_mem_calloc(size_t nitems, size_t size)
|
||||
{
|
||||
return k_calloc(nitems, size);
|
||||
}
|
||||
|
||||
void whd_mem_free(void *ptr)
|
||||
{
|
||||
k_free(ptr);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
51
drivers/wifi/infineon/airoc_whd_hal_common.h
Normal file
51
drivers/wifi/infineon/airoc_whd_hal_common.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or
|
||||
* an affiliate of Cypress Semiconductor Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <whd.h>
|
||||
#include <zephyr/device.h>
|
||||
|
||||
/** Defines the amount of stack memory available for the wifi thread. */
|
||||
#if !defined(CY_WIFI_THREAD_STACK_SIZE)
|
||||
#define CY_WIFI_THREAD_STACK_SIZE (5120)
|
||||
#endif
|
||||
|
||||
/** Defines the priority of the thread that services wifi packets. Legal values are defined by the
|
||||
* RTOS being used.
|
||||
*/
|
||||
#if !defined(CY_WIFI_THREAD_PRIORITY)
|
||||
#define CY_WIFI_THREAD_PRIORITY (CY_RTOS_PRIORITY_HIGH)
|
||||
#endif
|
||||
|
||||
/** Defines the country this will operate in for wifi initialization parameters. See the
|
||||
* wifi-host-driver's whd_country_code_t for legal options.
|
||||
*/
|
||||
#if !defined(CY_WIFI_COUNTRY)
|
||||
#define CY_WIFI_COUNTRY (WHD_COUNTRY_AUSTRALIA)
|
||||
#endif
|
||||
|
||||
/** Defines the priority of the interrupt that handles out-of-band notifications from the wifi
|
||||
* chip. Legal values are defined by the MCU running this code.
|
||||
*/
|
||||
#if !defined(CY_WIFI_OOB_INTR_PRIORITY)
|
||||
#define CY_WIFI_OOB_INTR_PRIORITY (2)
|
||||
#endif
|
||||
|
||||
/** Defines whether to use the out-of-band pin to allow the WIFI chip to wake up the MCU. */
|
||||
#if defined(CY_WIFI_HOST_WAKE_SW_FORCE)
|
||||
#define CY_USE_OOB_INTR (CY_WIFI_HOST_WAKE_SW_FORCE)
|
||||
#else
|
||||
#define CY_USE_OOB_INTR (1u)
|
||||
#endif /* defined(CY_WIFI_HOST_WAKE_SW_FORCE) */
|
||||
|
||||
#define CY_WIFI_HOST_WAKE_IRQ_EVENT GPIO_INT_TRIG_LOW
|
||||
#define DEFAULT_OOB_PIN (0)
|
||||
#define WLAN_POWER_UP_DELAY_MS (250)
|
||||
#define WLAN_CBUCK_DISCHARGE_MS (10)
|
||||
|
||||
extern whd_resource_source_t resource_ops;
|
||||
|
||||
int airoc_wifi_power_on(const struct device *dev);
|
|
@ -5,118 +5,36 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <airoc_wifi.h>
|
||||
#include "airoc_wifi.h"
|
||||
#include "airoc_whd_hal_common.h"
|
||||
|
||||
#include <bus_protocols/whd_bus_sdio_protocol.h>
|
||||
#include <bus_protocols/whd_bus.h>
|
||||
#include <bus_protocols/whd_sdio.h>
|
||||
#include <zephyr/sd/sd.h>
|
||||
#include <cy_utils.h>
|
||||
|
||||
#define DT_DRV_COMPAT infineon_airoc_wifi
|
||||
|
||||
LOG_MODULE_REGISTER(infineon_airoc, CONFIG_WIFI_LOG_LEVEL);
|
||||
LOG_MODULE_DECLARE(infineon_airoc_wifi, CONFIG_WIFI_LOG_LEVEL);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Defines the amount of stack memory available for the wifi thread. */
|
||||
#if !defined(CY_WIFI_THREAD_STACK_SIZE)
|
||||
#define CY_WIFI_THREAD_STACK_SIZE (5120)
|
||||
#endif
|
||||
|
||||
/** Defines the priority of the thread that services wifi packets. Legal values are defined by the
|
||||
* RTOS being used.
|
||||
*/
|
||||
#if !defined(CY_WIFI_THREAD_PRIORITY)
|
||||
#define CY_WIFI_THREAD_PRIORITY (CY_RTOS_PRIORITY_HIGH)
|
||||
#endif
|
||||
|
||||
/** Defines the country this will operate in for wifi initialization parameters. See the
|
||||
* wifi-host-driver's whd_country_code_t for legal options.
|
||||
*/
|
||||
#if !defined(CY_WIFI_COUNTRY)
|
||||
#define CY_WIFI_COUNTRY (WHD_COUNTRY_AUSTRALIA)
|
||||
#endif
|
||||
|
||||
/** Defines the priority of the interrupt that handles out-of-band notifications from the wifi
|
||||
* chip. Legal values are defined by the MCU running this code.
|
||||
*/
|
||||
#if !defined(CY_WIFI_OOB_INTR_PRIORITY)
|
||||
#define CY_WIFI_OOB_INTR_PRIORITY (2)
|
||||
#endif
|
||||
|
||||
/** Defines whether to use the out-of-band pin to allow the WIFI chip to wake up the MCU. */
|
||||
#if defined(CY_WIFI_HOST_WAKE_SW_FORCE)
|
||||
#define CY_USE_OOB_INTR (CY_WIFI_HOST_WAKE_SW_FORCE)
|
||||
#else
|
||||
#define CY_USE_OOB_INTR (1u)
|
||||
#endif /* defined(CY_WIFI_HOST_WAKE_SW_FORCE) */
|
||||
|
||||
#define CY_WIFI_HOST_WAKE_IRQ_EVENT GPIO_INT_TRIG_LOW
|
||||
#define DEFAULT_OOB_PIN (0)
|
||||
#define WLAN_POWER_UP_DELAY_MS (250)
|
||||
#define WLAN_CBUCK_DISCHARGE_MS (10)
|
||||
|
||||
extern whd_resource_source_t resource_ops;
|
||||
|
||||
struct whd_bus_priv {
|
||||
whd_sdio_config_t sdio_config;
|
||||
whd_bus_stats_t whd_bus_stats;
|
||||
whd_sdio_t sdio_obj;
|
||||
};
|
||||
|
||||
static whd_init_config_t init_config_default = {
|
||||
.thread_stack_size = CY_WIFI_THREAD_STACK_SIZE,
|
||||
.thread_stack_start = NULL,
|
||||
.thread_priority = (uint32_t)CY_WIFI_THREAD_PRIORITY,
|
||||
.country = CY_WIFI_COUNTRY
|
||||
};
|
||||
static whd_init_config_t init_config_default = {.thread_stack_size = CY_WIFI_THREAD_STACK_SIZE,
|
||||
.thread_stack_start = NULL,
|
||||
.thread_priority =
|
||||
(uint32_t)CY_WIFI_THREAD_PRIORITY,
|
||||
.country = CY_WIFI_COUNTRY};
|
||||
|
||||
/******************************************************
|
||||
* Function
|
||||
******************************************************/
|
||||
|
||||
int airoc_wifi_power_on(const struct device *dev)
|
||||
{
|
||||
#if DT_INST_NODE_HAS_PROP(0, wifi_reg_on_gpios)
|
||||
int ret;
|
||||
const struct airoc_wifi_config *config = dev->config;
|
||||
|
||||
/* Check WIFI REG_ON gpio instance */
|
||||
if (!device_is_ready(config->wifi_reg_on_gpio.port)) {
|
||||
LOG_ERR("Error: failed to configure wifi_reg_on %s pin %d",
|
||||
config->wifi_reg_on_gpio.port->name, config->wifi_reg_on_gpio.pin);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Configure wifi_reg_on as output */
|
||||
ret = gpio_pin_configure_dt(&config->wifi_reg_on_gpio, GPIO_OUTPUT);
|
||||
if (ret) {
|
||||
LOG_ERR("Error %d: failed to configure wifi_reg_on %s pin %d", ret,
|
||||
config->wifi_reg_on_gpio.port->name, config->wifi_reg_on_gpio.pin);
|
||||
return ret;
|
||||
}
|
||||
ret = gpio_pin_set_dt(&config->wifi_reg_on_gpio, 0);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Allow CBUCK regulator to discharge */
|
||||
(void)k_msleep(WLAN_CBUCK_DISCHARGE_MS);
|
||||
|
||||
/* WIFI power on */
|
||||
ret = gpio_pin_set_dt(&config->wifi_reg_on_gpio, 1);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
(void)k_msleep(WLAN_POWER_UP_DELAY_MS);
|
||||
#endif /* DT_INST_NODE_HAS_PROP(0, reg_on_gpios) */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int airoc_wifi_init_primary(const struct device *dev, whd_interface_t *interface,
|
||||
whd_netif_funcs_t *netif_funcs, whd_buffer_funcs_t *buffer_if)
|
||||
{
|
||||
|
@ -144,12 +62,12 @@ int airoc_wifi_init_primary(const struct device *dev, whd_interface_t *interface
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!device_is_ready(config->sdhc_dev)) {
|
||||
if (!device_is_ready(config->bus_dev.bus_sdio)) {
|
||||
LOG_ERR("SDHC device is not ready");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = sd_init(config->sdhc_dev, &data->card);
|
||||
ret = sd_init(config->bus_dev.bus_sdio, &data->card);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -415,25 +333,6 @@ whd_result_t whd_bus_sdio_enable_oob_intr(whd_driver_t whd_driver, whd_bool_t en
|
|||
return WHD_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement WHD memory wrappers
|
||||
*/
|
||||
|
||||
void *whd_mem_malloc(size_t size)
|
||||
{
|
||||
return k_malloc(size);
|
||||
}
|
||||
|
||||
void *whd_mem_calloc(size_t nitems, size_t size)
|
||||
{
|
||||
return k_calloc(nitems, size);
|
||||
}
|
||||
|
||||
void whd_mem_free(void *ptr)
|
||||
{
|
||||
k_free(ptr);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
288
drivers/wifi/infineon/airoc_whd_hal_spi.c
Normal file
288
drivers/wifi/infineon/airoc_whd_hal_spi.c
Normal file
|
@ -0,0 +1,288 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Stephen Boylan (stephen.boylan@beechwoods.com)
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <airoc_wifi.h>
|
||||
#include "airoc_whd_hal_common.h"
|
||||
|
||||
#include <bus_protocols/whd_bus_spi_protocol.h>
|
||||
#include <bus_protocols/whd_spi.h>
|
||||
#include <whd_wifi_api.h>
|
||||
#include <zephyr/drivers/spi.h>
|
||||
|
||||
LOG_MODULE_DECLARE(infineon_airoc_wifi, CONFIG_WIFI_LOG_LEVEL);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct whd_bus_priv {
|
||||
whd_spi_config_t spi_config;
|
||||
whd_spi_t spi_obj;
|
||||
};
|
||||
|
||||
static whd_init_config_t init_config_default = {.thread_stack_size = CY_WIFI_THREAD_STACK_SIZE,
|
||||
.thread_stack_start = NULL,
|
||||
.thread_priority =
|
||||
(uint32_t)CY_WIFI_THREAD_PRIORITY,
|
||||
.country = CY_WIFI_COUNTRY};
|
||||
|
||||
/******************************************************
|
||||
* Function
|
||||
******************************************************/
|
||||
|
||||
int airoc_wifi_init_primary(const struct device *dev, whd_interface_t *interface,
|
||||
whd_netif_funcs_t *netif_funcs,
|
||||
whd_buffer_funcs_t *buffer_if)
|
||||
{
|
||||
struct airoc_wifi_data *data = dev->data;
|
||||
const struct airoc_wifi_config *config = dev->config;
|
||||
|
||||
whd_spi_config_t whd_spi_config = {
|
||||
.is_spi_normal_mode = WHD_FALSE,
|
||||
};
|
||||
|
||||
#if DT_INST_NODE_HAS_PROP(0, wifi_host_wake_gpios)
|
||||
whd_oob_config_t oob_config = {
|
||||
.host_oob_pin = (void *)&config->wifi_host_wake_gpio,
|
||||
.dev_gpio_sel = DEFAULT_OOB_PIN,
|
||||
.is_falling_edge =
|
||||
(CY_WIFI_HOST_WAKE_IRQ_EVENT == GPIO_INT_TRIG_LOW) ? WHD_TRUE : WHD_FALSE,
|
||||
.intr_priority = CY_WIFI_OOB_INTR_PRIORITY};
|
||||
whd_spi_config.oob_config = oob_config;
|
||||
#endif
|
||||
#if defined(SPI_DATA_IRQ_SHARED)
|
||||
data->prev_irq_state = 0;
|
||||
#endif
|
||||
|
||||
/* Pull bus select line low before enabling WiFi chip */
|
||||
gpio_pin_configure_dt(&config->bus_select_gpio, GPIO_OUTPUT_INACTIVE);
|
||||
|
||||
if (airoc_wifi_power_on(dev)) {
|
||||
LOG_ERR("airoc_wifi_power_on returns fail");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!spi_is_ready_dt(&config->bus_dev.bus_spi)) {
|
||||
LOG_ERR("SPI device is not ready");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Init wifi host driver (whd) */
|
||||
cy_rslt_t whd_ret = whd_init(&data->whd_drv, &init_config_default,
|
||||
&resource_ops, buffer_if, netif_funcs);
|
||||
if (whd_ret == CY_RSLT_SUCCESS) {
|
||||
whd_ret = whd_bus_spi_attach(data->whd_drv, &whd_spi_config,
|
||||
(whd_spi_t)&config->bus_dev.bus_spi);
|
||||
|
||||
if (whd_ret == CY_RSLT_SUCCESS) {
|
||||
whd_ret = whd_wifi_on(data->whd_drv, interface);
|
||||
}
|
||||
|
||||
if (whd_ret != CY_RSLT_SUCCESS) {
|
||||
whd_deinit(*interface);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement SPI Transfer wrapper
|
||||
*/
|
||||
|
||||
whd_result_t whd_bus_spi_transfer(whd_driver_t whd_driver, const uint8_t *tx, size_t tx_length,
|
||||
uint8_t *rx, size_t rx_length, uint8_t write_fill)
|
||||
{
|
||||
const struct spi_dt_spec *spi_obj = whd_driver->bus_priv->spi_obj;
|
||||
int ret;
|
||||
whd_result_t whd_ret = WHD_SUCCESS;
|
||||
|
||||
#if defined(SPI_DATA_IRQ_SHARED)
|
||||
ret = whd_bus_spi_irq_enable(whd_driver, false);
|
||||
if (ret) {
|
||||
LOG_ERR("whd_bus_spi_irq_enable FAIL %d\n", ret);
|
||||
whd_ret = WHD_WLAN_SDIO_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* In some cases whd_bus_spi_protocol.c places the command at */
|
||||
/* the start of the rx buffer and passes NULL as the tx address, */
|
||||
/* reusing the same buffer (and overwriting the tx data). */
|
||||
if (tx == NULL && tx_length > 0 && rx_length >= tx_length) {
|
||||
tx = rx;
|
||||
}
|
||||
|
||||
const struct spi_buf tx_buf = {.buf = (uint8_t *)tx, .len = tx_length};
|
||||
const struct spi_buf_set tx_set = {.buffers = &tx_buf, .count = 1};
|
||||
struct spi_buf rx_buf[2];
|
||||
struct spi_buf_set rx_set = {.buffers = rx_buf, .count = 2};
|
||||
|
||||
if (rx != NULL) {
|
||||
rx += tx_length;
|
||||
}
|
||||
|
||||
if (rx_length >= tx_length) {
|
||||
rx_length -= tx_length;
|
||||
} else {
|
||||
rx_length = 0;
|
||||
}
|
||||
|
||||
if (spi_obj->config.operation & SPI_HALF_DUPLEX) {
|
||||
rx_buf[0].buf = rx;
|
||||
rx_buf[0].len = rx_length;
|
||||
rx_set.count = 1;
|
||||
} else {
|
||||
/* Talking to a half-duplex device via a full-duplex SPI driver, */
|
||||
/* it's necessary to ignore the data returned during send. The */
|
||||
/* SPI driver should not copy out the data if the buffer is NULL. */
|
||||
rx_buf[0].buf = NULL;
|
||||
rx_buf[0].len = tx_length;
|
||||
rx_buf[1].buf = rx;
|
||||
rx_buf[1].len = rx_length;
|
||||
}
|
||||
|
||||
ret = spi_transceive_dt(spi_obj, &tx_set, &rx_set);
|
||||
if (ret) {
|
||||
LOG_ERR("spi_transceive FAIL %d\n", ret);
|
||||
whd_ret = WHD_WLAN_SDIO_ERROR;
|
||||
}
|
||||
|
||||
#if defined(SPI_DATA_IRQ_SHARED)
|
||||
ret = whd_bus_spi_irq_enable(whd_driver, true);
|
||||
if (ret) {
|
||||
LOG_ERR("whd_bus_spi_irq_enable FAIL %d\n", ret);
|
||||
whd_ret = WHD_WLAN_SDIO_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
return whd_ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement OOB functionality
|
||||
*/
|
||||
|
||||
void whd_bus_spi_oob_irq_handler(const struct device *port, struct gpio_callback *cb,
|
||||
gpio_port_pins_t pins)
|
||||
{
|
||||
#if DT_INST_NODE_HAS_PROP(0, wifi_host_wake_gpios)
|
||||
struct airoc_wifi_data *data = CONTAINER_OF(cb, struct airoc_wifi_data, host_oob_pin_cb);
|
||||
|
||||
/* Get OOB pin info */
|
||||
const whd_oob_config_t *oob_config = &data->whd_drv->bus_priv->spi_config.oob_config;
|
||||
const struct gpio_dt_spec *host_oob_pin = oob_config->host_oob_pin;
|
||||
|
||||
/* Check OOB state is correct */
|
||||
int expected_event = (oob_config->is_falling_edge == WHD_TRUE) ? 0 : 1;
|
||||
|
||||
if (!(pins & BIT(host_oob_pin->pin)) || (gpio_pin_get_dt(host_oob_pin) != expected_event)) {
|
||||
WPRINT_WHD_ERROR(("Unexpected interrupt event %d\n", expected_event));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Call thread notify to wake up WHD thread */
|
||||
whd_thread_notify_irq(data->whd_drv);
|
||||
|
||||
#endif /* DT_INST_NODE_HAS_PROP(0, wifi-host-wake-gpios) */
|
||||
}
|
||||
|
||||
whd_result_t whd_bus_spi_irq_register(whd_driver_t whd_driver)
|
||||
{
|
||||
#if DT_INST_NODE_HAS_PROP(0, wifi_host_wake_gpios)
|
||||
int ret;
|
||||
const struct device *dev = DEVICE_DT_GET(DT_DRV_INST(0));
|
||||
struct airoc_wifi_data *data = dev->data;
|
||||
|
||||
/* Get OOB pin info */
|
||||
const whd_oob_config_t *oob_config = &whd_driver->bus_priv->spi_config.oob_config;
|
||||
const struct gpio_dt_spec *host_oob_pin = oob_config->host_oob_pin;
|
||||
|
||||
/* Check if OOB pin is ready */
|
||||
if (!gpio_is_ready_dt(host_oob_pin)) {
|
||||
WPRINT_WHD_ERROR(("%s: Failed at gpio_is_ready_dt for host_oob_pin\n", __func__));
|
||||
return WHD_HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Configure OOB pin as input */
|
||||
ret = gpio_pin_configure_dt(host_oob_pin, GPIO_INPUT);
|
||||
if (ret != 0) {
|
||||
WPRINT_WHD_ERROR((
|
||||
" %s: Failed at gpio_pin_configure_dt for host_oob_pin, result code = %d\n",
|
||||
__func__, ret));
|
||||
return WHD_HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Initialize/add OOB pin callback */
|
||||
gpio_init_callback(&data->host_oob_pin_cb, whd_bus_spi_oob_irq_handler,
|
||||
BIT(host_oob_pin->pin));
|
||||
|
||||
ret = gpio_add_callback_dt(host_oob_pin, &data->host_oob_pin_cb);
|
||||
if (ret != 0) {
|
||||
WPRINT_WHD_ERROR(
|
||||
("%s: Failed at gpio_add_callback_dt for host_oob_pin, result code = %d\n",
|
||||
__func__, ret));
|
||||
return WHD_HAL_ERROR;
|
||||
}
|
||||
#endif /* DT_INST_NODE_HAS_PROP(0, wifi_host_wake_gpios) */
|
||||
|
||||
return WHD_SUCCESS;
|
||||
}
|
||||
|
||||
whd_result_t whd_bus_spi_irq_enable(whd_driver_t whd_driver, whd_bool_t enable)
|
||||
{
|
||||
#if DT_INST_NODE_HAS_PROP(0, wifi_host_wake_gpios)
|
||||
int ret;
|
||||
const whd_oob_config_t *oob_config = &whd_driver->bus_priv->spi_config.oob_config;
|
||||
struct gpio_dt_spec *gpio = (struct gpio_dt_spec *)oob_config->host_oob_pin;
|
||||
|
||||
#if defined(SPI_DATA_IRQ_SHARED)
|
||||
const struct device *dev = DEVICE_DT_INST_GET(0);
|
||||
const struct airoc_wifi_config *config = dev->config;
|
||||
struct airoc_wifi_data *data = dev->data;
|
||||
|
||||
if (enable) {
|
||||
ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_HOST_WAKE);
|
||||
__ASSERT(ret == 0, "could not apply pinconfig, return code %d", ret);
|
||||
ret = gpio_pin_interrupt_configure_dt(
|
||||
gpio, (oob_config->is_falling_edge == WHD_TRUE) ? GPIO_INT_EDGE_FALLING
|
||||
: GPIO_INT_EDGE_RISING);
|
||||
__ASSERT(ret == 0, "gpio_pin_interrupt_configure_dt failed, return code %d", ret);
|
||||
|
||||
int state = gpio_pin_get_dt(gpio);
|
||||
int expected_event = (oob_config->is_falling_edge == WHD_TRUE) ? 0 : 1;
|
||||
|
||||
/* Notify only if interrupt wasn't assert before. This code assumes that if */
|
||||
/* the interrupt was previously asserted, then the thread has already been */
|
||||
/* notified. */
|
||||
if (state == expected_event && state != data->prev_irq_state) {
|
||||
whd_thread_notify_irq(whd_driver);
|
||||
}
|
||||
} else {
|
||||
data->prev_irq_state = gpio_pin_get_dt(gpio);
|
||||
ret = gpio_pin_interrupt_configure_dt(gpio, GPIO_INT_DISABLE);
|
||||
__ASSERT(ret == 0, "gpio_pin_interrupt_configure_dt failed, return code %d", ret);
|
||||
pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
|
||||
}
|
||||
#else
|
||||
if (enable) {
|
||||
ret = gpio_pin_interrupt_configure_dt(
|
||||
gpio, (oob_config->is_falling_edge == WHD_TRUE) ? GPIO_INT_EDGE_FALLING
|
||||
: GPIO_INT_EDGE_RISING);
|
||||
__ASSERT(ret == 0, "gpio_pin_interrupt_configure_dt failed, return code %d", ret);
|
||||
} else {
|
||||
ret = gpio_pin_interrupt_configure_dt(gpio, GPIO_INT_DISABLE);
|
||||
__ASSERT(ret == 0, "gpio_pin_interrupt_configure_dt failed, return code %d", ret);
|
||||
}
|
||||
#endif /* defined(SPI_DATA_IRQ_SHARED) */
|
||||
|
||||
#endif /* DT_INST_NODE_HAS_PROP(0, wifi_host_wake_gpios) */
|
||||
|
||||
return WHD_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
|
@ -9,11 +9,10 @@
|
|||
* @brief AIROC Wi-Fi driver.
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT infineon_airoc_wifi
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/net/conn_mgr/connectivity_wifi_mgmt.h>
|
||||
#include <airoc_wifi.h>
|
||||
#include <airoc_whd_hal_common.h>
|
||||
|
||||
LOG_MODULE_REGISTER(infineon_airoc_wifi, CONFIG_WIFI_LOG_LEVEL);
|
||||
|
||||
|
@ -76,8 +75,20 @@ static uint16_t sta_event_handler_index = 0xFF;
|
|||
static void airoc_event_task(void);
|
||||
static struct airoc_wifi_data airoc_wifi_data = {0};
|
||||
|
||||
#if defined(SPI_DATA_IRQ_SHARED)
|
||||
PINCTRL_DT_INST_DEFINE(0);
|
||||
#endif
|
||||
|
||||
static struct airoc_wifi_config airoc_wifi_config = {
|
||||
.sdhc_dev = DEVICE_DT_GET(DT_INST_PARENT(0)),
|
||||
#if defined(CONFIG_AIROC_WIFI_BUS_SDIO)
|
||||
.bus_dev.bus_sdio = DEVICE_DT_GET(DT_INST_PARENT(0)),
|
||||
#elif defined(CONFIG_AIROC_WIFI_BUS_SPI)
|
||||
.bus_dev.bus_spi = SPI_DT_SPEC_GET(DT_DRV_INST(0), AIROC_WIFI_SPI_OPERATION, 0),
|
||||
.bus_select_gpio = GPIO_DT_SPEC_GET_OR(DT_DRV_INST(0), bus_select_gpios, {0}),
|
||||
#if defined(SPI_DATA_IRQ_SHARED)
|
||||
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0),
|
||||
#endif
|
||||
#endif
|
||||
.wifi_reg_on_gpio = GPIO_DT_SPEC_GET_OR(DT_DRV_INST(0), wifi_reg_on_gpios, {0}),
|
||||
.wifi_host_wake_gpio = GPIO_DT_SPEC_GET_OR(DT_DRV_INST(0), wifi_host_wake_gpios, {0}),
|
||||
.wifi_dev_wake_gpio = GPIO_DT_SPEC_GET_OR(DT_DRV_INST(0), wifi_dev_wake_gpios, {0}),
|
||||
|
|
|
@ -6,16 +6,44 @@
|
|||
*/
|
||||
|
||||
#include <whd_buffer_api.h>
|
||||
#include <zephyr/sd/sd.h>
|
||||
#include <zephyr/sd/sdio.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/net/wifi_mgmt.h>
|
||||
|
||||
#ifdef CONFIG_AIROC_WIFI_BUS_SDIO
|
||||
#include <zephyr/sd/sd.h>
|
||||
#include <zephyr/sd/sdio.h>
|
||||
#endif
|
||||
#ifdef CONFIG_AIROC_WIFI_BUS_SPI
|
||||
#include <zephyr/drivers/spi.h>
|
||||
#endif
|
||||
|
||||
#include <cy_utils.h>
|
||||
|
||||
#define DT_DRV_COMPAT infineon_airoc_wifi
|
||||
|
||||
#if DT_PROP(DT_DRV_INST(0), spi_data_irq_shared)
|
||||
#define SPI_DATA_IRQ_SHARED
|
||||
#include <zephyr/drivers/pinctrl.h>
|
||||
|
||||
#define PINCTRL_STATE_HOST_WAKE PINCTRL_STATE_PRIV_START
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_AIROC_WIFI_BUS_SPI)
|
||||
#define AIROC_WIFI_SPI_OPERATION (SPI_WORD_SET(DT_PROP_OR(DT_DRV_INST(0), spi_word_size, 8)) \
|
||||
| (DT_PROP(DT_DRV_INST(0), spi_half_duplex) \
|
||||
? SPI_HALF_DUPLEX : SPI_FULL_DUPLEX) \
|
||||
| SPI_TRANSFER_MSB)
|
||||
#endif
|
||||
|
||||
struct airoc_wifi_data {
|
||||
#if defined(CONFIG_AIROC_WIFI_BUS_SDIO)
|
||||
struct sd_card card;
|
||||
struct sdio_func sdio_func1;
|
||||
struct sdio_func sdio_func2;
|
||||
#endif
|
||||
#if defined(SPI_DATA_IRQ_SHARED)
|
||||
uint8_t prev_irq_state;
|
||||
#endif
|
||||
struct net_if *iface;
|
||||
bool second_interface_init;
|
||||
bool is_ap_up;
|
||||
|
@ -34,11 +62,26 @@ struct airoc_wifi_data {
|
|||
uint8_t frame_buf[NET_ETH_MAX_FRAME_SIZE];
|
||||
};
|
||||
|
||||
union airoc_wifi_bus {
|
||||
#if defined(CONFIG_AIROC_WIFI_BUS_SDIO)
|
||||
const struct device *bus_sdio;
|
||||
#endif
|
||||
#if defined(CONFIG_AIROC_WIFI_BUS_SPI)
|
||||
const struct spi_dt_spec bus_spi;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct airoc_wifi_config {
|
||||
const struct device *sdhc_dev;
|
||||
const union airoc_wifi_bus bus_dev;
|
||||
struct gpio_dt_spec wifi_reg_on_gpio;
|
||||
struct gpio_dt_spec wifi_host_wake_gpio;
|
||||
struct gpio_dt_spec wifi_dev_wake_gpio;
|
||||
#if defined(CONFIG_AIROC_WIFI_BUS_SPI)
|
||||
struct gpio_dt_spec bus_select_gpio;
|
||||
#if defined(SPI_DATA_IRQ_SHARED)
|
||||
const struct pinctrl_dev_config *pcfg;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,4 +5,15 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* This is enpty/stub file used in WHD */
|
||||
/* required by whd_* header files. */
|
||||
|
||||
/* See cybsp_types.h, which is usually required by this file, but not available */
|
||||
/* here unless we pull in board-specific headers from the upstream driver. */
|
||||
#define CYBSP_SDIO_INTERFACE (0)
|
||||
#define CYBSP_SPI_INTERFACE (1)
|
||||
|
||||
#ifdef CONFIG_AIROC_WIFI_BUS_SDIO
|
||||
#define CYBSP_WIFI_INTERFACE_TYPE CYBSP_SDIO_INTERFACE
|
||||
#elif CONFIG_AIROC_WIFI_BUS_SPI
|
||||
#define CYBSP_WIFI_INTERFACE_TYPE CYBSP_SPI_INTERFACE
|
||||
#endif
|
||||
|
|
|
@ -49,7 +49,10 @@ zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/whd_wifi_p2p.c)
|
|||
# src/bus_protocols
|
||||
zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/bus_protocols/whd_bus.c)
|
||||
zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/bus_protocols/whd_bus_common.c)
|
||||
zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/src/bus_protocols/whd_bus_sdio_protocol.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_AIROC_WIFI_BUS_SDIO
|
||||
${hal_wifi_dir}/WiFi_Host_Driver/src/bus_protocols/whd_bus_sdio_protocol.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_AIROC_WIFI_BUS_SPI
|
||||
${hal_wifi_dir}/WiFi_Host_Driver/src/bus_protocols/whd_bus_spi_protocol.c)
|
||||
|
||||
# resources/resource_imp
|
||||
zephyr_library_sources(${hal_wifi_dir}/WiFi_Host_Driver/resources/resource_imp/whd_resources.c)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue