From 69ce178a42fe83f881403fad0077502414bdba02 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@gmail.com>
Date: Wed, 23 Jun 2021 19:54:56 +0200
Subject: [PATCH 057/484] cw1200: support loading cw1x60 FW

Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
 drivers/net/wireless/st/cw1200/fwio.c | 47 +++++++++++++++++++++++----
 drivers/net/wireless/st/cw1200/hwio.h |  1 +
 2 files changed, 42 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/st/cw1200/fwio.c b/drivers/net/wireless/st/cw1200/fwio.c
index 2a03dc533b6a..a71e90fff616 100644
--- a/drivers/net/wireless/st/cw1200/fwio.c
+++ b/drivers/net/wireless/st/cw1200/fwio.c
@@ -48,6 +48,39 @@ static int cw1200_get_hw_type(u32 config_reg_val, int *major_revision)
 	return hw_type;
 }
 
+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;
+	int ret;
+
+	ret = request_firmware(&bootloader, bl_path, priv->pdev);
+	if (ret) {
+		pr_err("Can't load bootloader file %s.\n", bl_path);
+		goto error;
+	}
+
+	data = (u32 *)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 < 0)
+			goto error;
+		ret = cw1200_reg_write_32(priv,
+					  ST90TDS_AHB_DPORT_REG_ID, data[i]);
+		if (ret < 0)
+			goto error;
+	}
+
+	pr_info("Bootloader download complete\n");
+
+error:
+	release_firmware(bootloader);
+
+	return ret;
+}
+
 static int cw1200_load_firmware_cw1200(struct cw1200_common *priv)
 {
 	int ret, block, num_blocks;
@@ -128,9 +161,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);
+	if (priv->hw_revision != CW1X60_HW_REV) {
+		/* Write the NOP Instruction */
+		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);
@@ -469,9 +504,9 @@ 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_bootloader(priv);
+			if (ret)
+				goto out;
 		}
 		ret = cw1200_load_firmware_cw1200(priv);
 		break;
diff --git a/drivers/net/wireless/st/cw1200/hwio.h b/drivers/net/wireless/st/cw1200/hwio.h
index d1e629a566c2..e2d0fb2d02ef 100644
--- a/drivers/net/wireless/st/cw1200/hwio.h
+++ b/drivers/net/wireless/st/cw1200/hwio.h
@@ -89,6 +89,7 @@ struct download_cntl_t {
 
 
 #define SYS_BASE_ADDR_SILICON		(0)
+#define AHB_MEMORY_ADDRESS		(SYS_BASE_ADDR_SILICON + 0x08000000)
 #define PAC_BASE_ADDRESS_SILICON	(SYS_BASE_ADDR_SILICON + 0x09000000)
 #define PAC_SHARED_MEMORY_SILICON	(PAC_BASE_ADDRESS_SILICON)
 
-- 
2.49.0

