From: Pablo Mazzini <pmazzini@gmail.com>
To: linux-wireless@vger.kernel.org
Cc: Pablo Mazzini <pmazzini@gmail.com>, Ulf Hansson <ulfh@kernel.org>,
linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH wireless-next 4/4] wifi: cw1200: add XRadio XR819 support
Date: Mon, 2 Nov 2026 17:16:03 +0000 [thread overview]
Message-ID: <20261102171603.368298-5-pmazzini@gmail.com> (raw)
In-Reply-To: <20261102171603.368298-1-pmazzini@gmail.com>
The XR819 uses the ST-E SDIO vendor ID with device ID 0x2281 and
reports itself as a CW1x60. It starts from a bootloader written into
its memory, then takes the usual firmware download. Its modules run
from a 24 MHz reference clock.
Give the CW1x60 entry the XR819 bootloader and firmware, and load the
bootloader instead of the NOP instruction.
Signed-off-by: Pablo Mazzini <pmazzini@gmail.com>
---
drivers/net/wireless/st/cw1200/Kconfig | 3 +-
drivers/net/wireless/st/cw1200/cw1200_sdio.c | 13 ++++-
drivers/net/wireless/st/cw1200/fwio.c | 58 ++++++++++++++++----
drivers/net/wireless/st/cw1200/fwio.h | 7 ++-
include/linux/mmc/sdio_ids.h | 1 +
5 files changed, 66 insertions(+), 16 deletions(-)
diff --git a/drivers/net/wireless/st/cw1200/Kconfig b/drivers/net/wireless/st/cw1200/Kconfig
index 03575e9894bb..9404e318137c 100644
--- a/drivers/net/wireless/st/cw1200/Kconfig
+++ b/drivers/net/wireless/st/cw1200/Kconfig
@@ -3,7 +3,8 @@ config CW1200
tristate "CW1200 WLAN support"
depends on MAC80211 && CFG80211
help
- This is a driver for the ST-E CW1100 & CW1200 WLAN chipsets.
+ This is a driver for the ST-E CW1100 & CW1200 and the XRadio
+ XR819 WLAN chipsets.
This option just enables the driver core, see below for
specific bus support.
diff --git a/drivers/net/wireless/st/cw1200/cw1200_sdio.c b/drivers/net/wireless/st/cw1200/cw1200_sdio.c
index 2b6afe221268..3db937785cab 100644
--- a/drivers/net/wireless/st/cw1200/cw1200_sdio.c
+++ b/drivers/net/wireless/st/cw1200/cw1200_sdio.c
@@ -35,6 +35,12 @@ static struct cw1200_platform_data_sdio sagrad_109x_evk_platform_data = {
.sdd_file = "sdd_sagrad_1091_1098.bin",
};
+/* XRadio XR819 modules, with a 24 MHz reference clock */
+static const struct cw1200_platform_data_sdio xr819_platform_data = {
+ .ref_clk = 24000,
+ .have_5ghz = false,
+};
+
/* Allow platform data to be overridden */
static struct cw1200_platform_data_sdio *global_plat_data = &sagrad_109x_evk_platform_data;
@@ -51,6 +57,8 @@ struct hwbus_priv {
static const struct sdio_device_id cw1200_sdio_ids[] = {
{ SDIO_DEVICE(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200) },
+ { SDIO_DEVICE(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_XR819),
+ .driver_data = (kernel_ulong_t)&xr819_platform_data },
{ /* end: all zeroes */ },
};
MODULE_DEVICE_TABLE(sdio, cw1200_sdio_ids);
@@ -295,7 +303,10 @@ static int cw1200_sdio_probe(struct sdio_func *func,
func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
- self->pdata = global_plat_data; /* FIXME */
+ if (id->driver_data)
+ self->pdata = (const void *)id->driver_data;
+ else
+ self->pdata = global_plat_data; /* FIXME */
self->func = func;
sdio_set_drvdata(func, self);
sdio_claim_host(func);
diff --git a/drivers/net/wireless/st/cw1200/fwio.c b/drivers/net/wireless/st/cw1200/fwio.c
index 1a68ef6ed2fa..6b885fd717db 100644
--- a/drivers/net/wireless/st/cw1200/fwio.c
+++ b/drivers/net/wireless/st/cw1200/fwio.c
@@ -66,9 +66,10 @@ static const struct cw1200_chip cw1200_chips[] = {
.firmware = FIRMWARE_CUT22,
.sdd = SDD_FILE_22,
}, {
- .revision = CW1X60_HW_REV,
- .firmware = FIRMWARE_CW1X60,
- .sdd = SDD_FILE_CW1X60,
+ .revision = CW1X60_HW_REV, /* XRadio XR819 */
+ .bootloader = BOOTLOADER_XR819,
+ .firmware = FIRMWARE_XR819,
+ .sdd = SDD_FILE_XR819,
.sync_join = true,
.no_switch_channel = true,
},
@@ -85,6 +86,38 @@ static const struct cw1200_chip *cw1200_find_chip(int revision)
return NULL;
}
+/* The bootloader is written word by word into the AHB memory */
+static int cw1200_load_bootloader(struct cw1200_common *priv)
+{
+ const struct firmware *bootloader;
+ const __le32 *data;
+ u32 addr = 0x08000000;
+ size_t i;
+ int ret;
+
+ ret = request_firmware(&bootloader, priv->chip->bootloader, priv->pdev);
+ if (ret) {
+ pr_err("Can't load bootloader file %s.\n", priv->chip->bootloader);
+ return ret;
+ }
+
+ data = (const __le32 *)bootloader->data;
+ for (i = 0; i < bootloader->size / 4; i++, addr += 4) {
+ ret = cw1200_reg_write_32(priv, ST90TDS_SRAM_BASE_ADDR_REG_ID,
+ addr);
+ if (!ret)
+ ret = cw1200_reg_write_32(priv, ST90TDS_AHB_DPORT_REG_ID,
+ le32_to_cpu(data[i]));
+ if (ret) {
+ pr_err("Can't write bootloader.\n");
+ break;
+ }
+ }
+
+ release_firmware(bootloader);
+ return ret;
+}
+
static int cw1200_load_firmware_cw1200(struct cw1200_common *priv)
{
int ret, block, num_blocks;
@@ -136,6 +169,12 @@ static int cw1200_load_firmware_cw1200(struct cw1200_common *priv)
if (!priv->sdd_path)
priv->sdd_path = priv->chip->sdd;
+ if (priv->chip->bootloader) {
+ ret = cw1200_load_bootloader(priv);
+ if (ret)
+ return ret;
+ }
+
/* Initialize common registers */
APB_WRITE(DOWNLOAD_IMAGE_SIZE_REG, DOWNLOAD_ARE_YOU_HERE);
APB_WRITE(DOWNLOAD_PUT_REG, 0);
@@ -143,9 +182,11 @@ static int cw1200_load_firmware_cw1200(struct cw1200_common *priv)
APB_WRITE(DOWNLOAD_STATUS_REG, DOWNLOAD_PENDING);
APB_WRITE(DOWNLOAD_FLAGS_REG, 0);
- /* Write the NOP Instruction */
- REG_WRITE(ST90TDS_SRAM_BASE_ADDR_REG_ID, 0xFFF20000);
- REG_WRITE(ST90TDS_AHB_DPORT_REG_ID, 0xEAFFFFFE);
+ /* Write the NOP Instruction, unless the bootloader runs instead */
+ if (!priv->chip->bootloader) {
+ REG_WRITE(ST90TDS_SRAM_BASE_ADDR_REG_ID, 0xFFF20000);
+ REG_WRITE(ST90TDS_AHB_DPORT_REG_ID, 0xEAFFFFFE);
+ }
/* Release CPU from RESET */
REG_READ(ST90TDS_CONFIG_REG_ID, val32);
@@ -483,11 +524,6 @@ int cw1200_load_firmware(struct cw1200_common *priv)
switch (priv->hw_type) {
case HIF_8601_SILICON:
- if (priv->hw_revision == CW1X60_HW_REV) {
- pr_err("Can't handle CW1160/1260 firmware load yet.\n");
- ret = -ENOTSUPP;
- goto out;
- }
ret = cw1200_load_firmware_cw1200(priv);
break;
default:
diff --git a/drivers/net/wireless/st/cw1200/fwio.h b/drivers/net/wireless/st/cw1200/fwio.h
index 9925d4bcedda..fb66d564c304 100644
--- a/drivers/net/wireless/st/cw1200/fwio.h
+++ b/drivers/net/wireless/st/cw1200/fwio.h
@@ -14,13 +14,13 @@
#ifndef FWIO_H_INCLUDED
#define FWIO_H_INCLUDED
-#define BOOTLOADER_CW1X60 "boot_cw1x60.bin"
-#define FIRMWARE_CW1X60 "wsm_cw1x60.bin"
+#define BOOTLOADER_XR819 "xr819/boot_xr819.bin"
+#define FIRMWARE_XR819 "xr819/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_XR819 "xr819/sdd_xr819.bin"
#define SDD_FILE_22 "sdd_22.bin"
#define SDD_FILE_20 "sdd_20.bin"
#define SDD_FILE_11 "sdd_11.bin"
@@ -28,6 +28,7 @@
struct cw1200_chip {
int revision;
+ const char *bootloader; /* NULL: write the NOP instruction */
const char *firmware;
const char *sdd;
bool sync_join; /* no asynchronous join */
diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h
index dfffda3d8002..35789be747a5 100644
--- a/include/linux/mmc/sdio_ids.h
+++ b/include/linux/mmc/sdio_ids.h
@@ -27,6 +27,7 @@
#define SDIO_VENDOR_ID_STE 0x0020
#define SDIO_DEVICE_ID_STE_CW1200 0x2280
+#define SDIO_DEVICE_ID_STE_XR819 0x2281
#define SDIO_VENDOR_ID_INTEL 0x0089
#define SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX 0x1402
--
2.52.0
prev parent reply other threads:[~2026-11-02 17:16 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-02 17:15 [PATCH wireless-next 0/4] " Pablo Mazzini
2026-11-02 17:16 ` [PATCH wireless-next 1/4] wifi: cw1200: don't update the beacon in station mode Pablo Mazzini
2026-11-02 17:16 ` [PATCH wireless-next 2/4] wifi: cw1200: describe the chips in a table Pablo Mazzini
2026-11-02 17:16 ` [PATCH wireless-next 3/4] wifi: cw1200: handle the XR819 channel switch and join Pablo Mazzini
2026-11-02 17:16 ` Pablo Mazzini [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261102171603.368298-5-pmazzini@gmail.com \
--to=pmazzini@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mmc@vger.kernel.org \
--cc=linux-wireless@vger.kernel.org \
--cc=ulfh@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®