build/patch/kernel/archive/sunxi-6.5/patches.megous/cw1200-xr819-hacks.patch

392 lines
13 KiB
Diff

From 623947c85005d76dab4021f33b3b3fdadee9dac4 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@gmail.com>
Date: Sat, 3 Jul 2021 08:59:21 +0200
Subject: [PATCH 417/464] cw1200: xr819 hacks
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
drivers/net/wireless/st/cw1200/cw1200.h | 7 ++-
drivers/net/wireless/st/cw1200/cw1200_sdio.c | 59 ++++++++++++++++++--
drivers/net/wireless/st/cw1200/cw1200_spi.c | 3 +-
drivers/net/wireless/st/cw1200/fwio.c | 20 +++++--
drivers/net/wireless/st/cw1200/fwio.h | 3 +
drivers/net/wireless/st/cw1200/main.c | 9 ++-
drivers/net/wireless/st/cw1200/queue.h | 7 ++-
drivers/net/wireless/st/cw1200/sta.c | 46 ++++++++-------
drivers/net/wireless/st/cw1200/wsm.c | 9 +++
9 files changed, 128 insertions(+), 35 deletions(-)
diff --git a/drivers/net/wireless/st/cw1200/cw1200.h b/drivers/net/wireless/st/cw1200/cw1200.h
index 48f808cdc1cb..22bf12ea2859 100644
--- a/drivers/net/wireless/st/cw1200/cw1200.h
+++ b/drivers/net/wireless/st/cw1200/cw1200.h
@@ -117,6 +117,10 @@ struct cw1200_common {
CW1200_HW_REV_CUT22 = 22,
CW1X60_HW_REV = 40,
} hw_revision;
+ enum cw1200_fw_api {
+ CW1200_FW_API_ORIGINAL = 0,
+ CW1200_FW_API_XRADIO,
+ } fw_api;
int hw_refclk;
bool hw_have_5ghz;
const struct firmware *sdd;
@@ -292,7 +296,8 @@ int cw1200_core_probe(const struct hwbus_ops *hwbus_ops,
struct device *pdev,
struct cw1200_common **pself,
int ref_clk, const u8 *macaddr,
- const char *sdd_path, bool have_5ghz);
+ const char *sdd_path, bool have_5ghz,
+ unsigned int fw_api);
void cw1200_core_release(struct cw1200_common *self);
#define FWLOAD_BLOCK_SIZE (1024)
diff --git a/drivers/net/wireless/st/cw1200/cw1200_sdio.c b/drivers/net/wireless/st/cw1200/cw1200_sdio.c
index 4c30b5772ce0..dd0c76c16398 100644
--- a/drivers/net/wireless/st/cw1200/cw1200_sdio.c
+++ b/drivers/net/wireless/st/cw1200/cw1200_sdio.c
@@ -15,6 +15,9 @@
#include <linux/mmc/card.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/sdio_ids.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_net.h>
#include <net/mac80211.h>
#include "cw1200.h"
@@ -30,9 +33,7 @@ MODULE_LICENSE("GPL");
/* Default platform data for Sagrad modules */
static struct cw1200_platform_data_sdio sagrad_109x_evk_platform_data = {
- .ref_clk = 38400,
- .have_5ghz = false,
- .sdd_file = "sdd_sagrad_1091_1098.bin",
+ .ref_clk = 24000,
};
/* Allow platform data to be overridden */
@@ -50,8 +51,15 @@ struct hwbus_priv {
};
static const struct sdio_device_id cw1200_sdio_ids[] = {
- { SDIO_DEVICE(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200) },
- { /* end: all zeroes */ },
+ {
+ SDIO_DEVICE(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200),
+ .driver_data = CW1200_FW_API_ORIGINAL
+ },
+ {
+ SDIO_DEVICE(SDIO_VENDOR_ID_STE, 0x2281),
+ .driver_data = CW1200_FW_API_XRADIO
+ },
+ { /* end: all zeroes */ },
};
MODULE_DEVICE_TABLE(sdio, cw1200_sdio_ids);
@@ -266,6 +274,41 @@ static const struct hwbus_ops cw1200_sdio_hwbus_ops = {
.power_mgmt = cw1200_sdio_pm,
};
+static const struct of_device_id xradio_sdio_of_match_table[] = {
+ { .compatible = "xradio,xr819" },
+ { }
+};
+
+static int cw1200_probe_of(struct sdio_func *func)
+{
+ struct device *dev = &func->dev;
+ struct device_node *np = dev->of_node;
+ const struct of_device_id *of_id;
+ u8 *macaddr;
+ int irq;
+
+ of_id = of_match_node(xradio_sdio_of_match_table, np);
+ if (!of_id)
+ return -ENODEV;
+
+ irq = irq_of_parse_and_map(np, 0);
+ if (!irq) {
+ pr_err("SDIO: No irq in platform data\n");
+ return -EINVAL;
+ }
+
+ global_plat_data->irq = irq;
+
+ macaddr = devm_kmalloc(dev, ETH_ALEN, GFP_KERNEL);
+ if (!macaddr)
+ return -ENOMEM;
+
+ if (!of_get_mac_address(np, macaddr))
+ global_plat_data->macaddr = macaddr;
+
+ return 0;
+}
+
/* Probe Function to be called by SDIO stack when device is discovered */
static int cw1200_sdio_probe(struct sdio_func *func,
const struct sdio_device_id *id)
@@ -279,6 +322,8 @@ static int cw1200_sdio_probe(struct sdio_func *func,
if (func->num != 0x01)
return -ENODEV;
+ cw1200_probe_of(func);
+
self = kzalloc(sizeof(*self), GFP_KERNEL);
if (!self) {
pr_err("Can't allocate SDIO hwbus_priv.\n");
@@ -286,6 +331,7 @@ static int cw1200_sdio_probe(struct sdio_func *func,
}
func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
+ func->card->quirks |= MMC_QUIRK_BROKEN_BYTE_MODE_512;
self->pdata = global_plat_data; /* FIXME */
self->func = func;
@@ -301,7 +347,8 @@ static int cw1200_sdio_probe(struct sdio_func *func,
self->pdata->ref_clk,
self->pdata->macaddr,
self->pdata->sdd_file,
- self->pdata->have_5ghz);
+ self->pdata->have_5ghz,
+ id->driver_data);
if (status) {
cw1200_sdio_irq_unsubscribe(self);
sdio_claim_host(func);
diff --git a/drivers/net/wireless/st/cw1200/cw1200_spi.c b/drivers/net/wireless/st/cw1200/cw1200_spi.c
index c82c0688b549..51a13673c726 100644
--- a/drivers/net/wireless/st/cw1200/cw1200_spi.c
+++ b/drivers/net/wireless/st/cw1200/cw1200_spi.c
@@ -412,7 +412,8 @@ static int cw1200_spi_probe(struct spi_device *func)
self->pdata->ref_clk,
self->pdata->macaddr,
self->pdata->sdd_file,
- self->pdata->have_5ghz);
+ self->pdata->have_5ghz,
+ CW1200_FW_API_ORIGINAL);
if (status) {
cw1200_spi_irq_unsubscribe(self);
diff --git a/drivers/net/wireless/st/cw1200/fwio.c b/drivers/net/wireless/st/cw1200/fwio.c
index a71e90fff616..55cd897a9d4d 100644
--- a/drivers/net/wireless/st/cw1200/fwio.c
+++ b/drivers/net/wireless/st/cw1200/fwio.c
@@ -51,10 +51,15 @@ static int cw1200_get_hw_type(u32 config_reg_val, int *major_revision)
static int cw1200_load_bootloader(struct cw1200_common *priv)
{
const struct firmware *bootloader = NULL;
- const char *bl_path = BOOTLOADER_CW1X60;
u32 *data, i, addr = AHB_MEMORY_ADDRESS;
+ const char *bl_path;
int ret;
+ if (priv->fw_api == CW1200_FW_API_XRADIO)
+ bl_path = BOOTLOADER_XRADIO;
+ else
+ bl_path = BOOTLOADER_CW1X60;
+
ret = request_firmware(&bootloader, bl_path, priv->pdev);
if (ret) {
pr_err("Can't load bootloader file %s.\n", bl_path);
@@ -145,9 +150,16 @@ static int cw1200_load_firmware_cw1200(struct cw1200_common *priv)
priv->sdd_path = SDD_FILE_22;
break;
case CW1X60_HW_REV:
- fw_path = FIRMWARE_CW1X60;
- if (!priv->sdd_path)
- priv->sdd_path = SDD_FILE_CW1X60;
+ if (priv->fw_api == CW1200_FW_API_XRADIO)
+ fw_path = FIRMWARE_XRADIO;
+ else
+ fw_path = FIRMWARE_CW1X60;
+ if (!priv->sdd_path) {
+ if (priv->fw_api == CW1200_FW_API_XRADIO)
+ priv->sdd_path = SDD_FILE_XRADIO;
+ else
+ priv->sdd_path = SDD_FILE_CW1X60;
+ }
break;
default:
pr_err("Invalid silicon revision %d.\n", priv->hw_revision);
diff --git a/drivers/net/wireless/st/cw1200/fwio.h b/drivers/net/wireless/st/cw1200/fwio.h
index c287160a492e..e18f7628cf4c 100644
--- a/drivers/net/wireless/st/cw1200/fwio.h
+++ b/drivers/net/wireless/st/cw1200/fwio.h
@@ -15,12 +15,15 @@
#define FWIO_H_INCLUDED
#define BOOTLOADER_CW1X60 "boot_cw1x60.bin"
+#define BOOTLOADER_XRADIO "boot_xr819.bin"
#define FIRMWARE_CW1X60 "wsm_cw1x60.bin"
+#define FIRMWARE_XRADIO "fw_xr819.bin"
#define FIRMWARE_CUT22 "wsm_22.bin"
#define FIRMWARE_CUT20 "wsm_20.bin"
#define FIRMWARE_CUT11 "wsm_11.bin"
#define FIRMWARE_CUT10 "wsm_10.bin"
#define SDD_FILE_CW1X60 "sdd_cw1x60.bin"
+#define SDD_FILE_XRADIO "sdd_xr819.bin"
#define SDD_FILE_22 "sdd_22.bin"
#define SDD_FILE_20 "sdd_20.bin"
#define SDD_FILE_11 "sdd_11.bin"
diff --git a/drivers/net/wireless/st/cw1200/main.c b/drivers/net/wireless/st/cw1200/main.c
index 381013e0db63..bb8aa291e055 100644
--- a/drivers/net/wireless/st/cw1200/main.c
+++ b/drivers/net/wireless/st/cw1200/main.c
@@ -251,7 +251,8 @@ static const struct wiphy_wowlan_support cw1200_wowlan_support = {
static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr,
- const bool have_5ghz)
+ const bool have_5ghz,
+ unsigned int fw_api)
{
int i, band;
struct ieee80211_hw *hw;
@@ -267,6 +268,7 @@ static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr,
priv->mode = NL80211_IFTYPE_UNSPECIFIED;
priv->rates = cw1200_rates; /* TODO: fetch from FW */
priv->mcs_rates = cw1200_n_rates;
+ priv->fw_api = fw_api;
if (cw1200_ba_rx_tids != -1)
priv->ba_rx_tid_mask = cw1200_ba_rx_tids;
else
@@ -518,7 +520,8 @@ int cw1200_core_probe(const struct hwbus_ops *hwbus_ops,
struct device *pdev,
struct cw1200_common **core,
int ref_clk, const u8 *macaddr,
- const char *sdd_path, bool have_5ghz)
+ const char *sdd_path, bool have_5ghz,
+ unsigned int fw_api)
{
int err = -EINVAL;
struct ieee80211_hw *dev;
@@ -528,7 +531,7 @@ int cw1200_core_probe(const struct hwbus_ops *hwbus_ops,
.disable_more_flag_usage = true,
};
- dev = cw1200_init_common(macaddr, have_5ghz);
+ dev = cw1200_init_common(macaddr, have_5ghz, fw_api);
if (!dev)
goto err;
diff --git a/drivers/net/wireless/st/cw1200/queue.h b/drivers/net/wireless/st/cw1200/queue.h
index 96ac69ae97de..103b56d81b9e 100644
--- a/drivers/net/wireless/st/cw1200/queue.h
+++ b/drivers/net/wireless/st/cw1200/queue.h
@@ -102,7 +102,12 @@ bool cw1200_queue_stats_is_empty(struct cw1200_queue_stats *stats,
static inline u8 cw1200_queue_get_queue_id(u32 packet_id)
{
- return (packet_id >> 16) & 0xFF;
+ return (packet_id >> 16) & 0xF;
+}
+
+static inline u8 cw1200_queue_get_link_id(u32 packet_id)
+{
+ return (packet_id >> 24) & 0xF;
}
static inline u8 cw1200_queue_get_generation(u32 packet_id)
diff --git a/drivers/net/wireless/st/cw1200/sta.c b/drivers/net/wireless/st/cw1200/sta.c
index 8ef1d06b9bbd..209216fcd4c3 100644
--- a/drivers/net/wireless/st/cw1200/sta.c
+++ b/drivers/net/wireless/st/cw1200/sta.c
@@ -343,28 +343,34 @@ int cw1200_config(struct ieee80211_hw *dev, u32 changed)
if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) &&
(priv->channel != conf->chandef.chan)) {
struct ieee80211_channel *ch = conf->chandef.chan;
- struct wsm_switch_channel channel = {
- .channel_number = ch->hw_value,
- };
+
pr_debug("[STA] Freq %d (wsm ch: %d).\n",
ch->center_freq, ch->hw_value);
- /* __cw1200_flush() implicitly locks tx, if successful */
- if (!__cw1200_flush(priv, false)) {
- if (!wsm_switch_channel(priv, &channel)) {
- ret = wait_event_timeout(priv->channel_switch_done,
- !priv->channel_switch_in_progress,
- 3 * HZ);
- if (ret) {
- /* Already unlocks if successful */
- priv->channel = ch;
- ret = 0;
+ if (priv->fw_api == CW1200_FW_API_XRADIO) {
+ priv->channel = ch;
+ } else {
+ struct wsm_switch_channel channel = {
+ .channel_number = ch->hw_value,
+ };
+
+ /* __cw1200_flush() implicitly locks tx, if successful */
+ if (!__cw1200_flush(priv, false)) {
+ if (!wsm_switch_channel(priv, &channel)) {
+ ret = wait_event_timeout(priv->channel_switch_done,
+ !priv->channel_switch_in_progress,
+ 3 * HZ);
+ if (ret) {
+ /* Already unlocks if successful */
+ priv->channel = ch;
+ ret = 0;
+ } else {
+ ret = -ETIMEDOUT;
+ }
} else {
- ret = -ETIMEDOUT;
+ /* Unlock if switch channel fails */
+ wsm_unlock_tx(priv);
}
- } else {
- /* Unlock if switch channel fails */
- wsm_unlock_tx(priv);
}
}
}
@@ -1303,7 +1309,7 @@ static void cw1200_do_join(struct cw1200_common *priv)
}
/* Enable asynchronous join calls */
- if (!priv->vif->cfg.ibss_joined) {
+ if (priv->fw_api != CW1200_FW_API_XRADIO && !priv->vif->cfg.ibss_joined) {
join.flags |= WSM_JOIN_FLAGS_FORCE;
join.flags |= WSM_JOIN_FLAGS_FORCE_WITH_COMPLETE_IND;
}
@@ -1743,7 +1749,9 @@ void cw1200_set_cts_work(struct work_struct *work)
wsm_write_mib(priv, WSM_MIB_ID_NON_ERP_PROTECTION,
&use_cts_prot, sizeof(use_cts_prot));
- wsm_update_ie(priv, &update_ie);
+ if (priv->fw_api != CW1200_FW_API_XRADIO ||
+ priv->mode != NL80211_IFTYPE_STATION)
+ wsm_update_ie(priv, &update_ie);
return;
}
diff --git a/drivers/net/wireless/st/cw1200/wsm.c b/drivers/net/wireless/st/cw1200/wsm.c
index 4a9e4b5d3547..ee378265aee5 100644
--- a/drivers/net/wireless/st/cw1200/wsm.c
+++ b/drivers/net/wireless/st/cw1200/wsm.c
@@ -360,9 +360,18 @@ static int wsm_tx_confirm(struct cw1200_common *priv,
tx_confirm.tx_rate = WSM_GET8(buf);
tx_confirm.ack_failures = WSM_GET8(buf);
tx_confirm.flags = WSM_GET16(buf);
+ if (priv->fw_api == CW1200_FW_API_XRADIO) {
+ /* rate_try[3] */
+ WSM_GET32(buf);
+ WSM_GET32(buf);
+ WSM_GET32(buf);
+ }
tx_confirm.media_delay = WSM_GET32(buf);
tx_confirm.tx_queue_delay = WSM_GET32(buf);
+ if (priv->fw_api == CW1200_FW_API_XRADIO)
+ link_id = cw1200_queue_get_link_id(tx_confirm.packet_id);
+
cw1200_tx_confirm_cb(priv, link_id, &tx_confirm);
return 0;
--
2.34.1