From f0d858c2d65cb0dafcb5abe694bd047ced8538f7 Mon Sep 17 00:00:00 2001
From: avishad verma <avishad.verma@infineon.com>
Date: Tue, 6 Feb 2024 11:14:35 -0600
Subject: [PATCH 262/296] brcmfmac: Hatched-1 DDR50 CRC error KSO Change

After PM2 sleep exit data CRC is reported for First CMD53.
Although the packet at the device side is intact, but device responded
with CRC error.
KSO ON sequence is changed with additional chip id read to fix this.

Signed-off-by: avishad verma <avishad.verma@infineon.com>
---
 .../broadcom/brcm80211/brcmfmac/bcmsdh.c      | 14 ++--
 .../broadcom/brcm80211/brcmfmac/sdio.c        | 83 ++++++++++++-------
 2 files changed, 62 insertions(+), 35 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index 12356174efe4..fad32b24c009 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -234,7 +234,7 @@ static int brcmf_sdiod_set_backplane_window(struct brcmf_sdio_dev *sdiodev,
 	int err = 0, i;
 
 	if (brcmf_sdio_bus_sleep_state(sdiodev->bus)) {
-		brcmf_err("WARN: Write operation when bus is in sleep state\n");
+		brcmf_err("ERROR: Write operation when bus is in sleep state\n");
 	}
 
 	if (sdiodev->sbwad_valid && (bar0 == sdiodev->sbwad))
@@ -260,7 +260,7 @@ u32 brcmf_sdiod_readl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
 	int retval;
 
 	if (brcmf_sdio_bus_sleep_state(sdiodev->bus)) {
-		brcmf_err("WARN: Read operation when bus is in sleep state\n");
+		brcmf_err("ERROR: Read operation when bus is in sleep state\n");
 	}
 
 	retval = brcmf_sdiod_set_backplane_window(sdiodev, addr);
@@ -288,7 +288,7 @@ void brcmf_sdiod_writel(struct brcmf_sdio_dev *sdiodev, u32 addr,
 	int retval;
 
 	if (brcmf_sdio_bus_sleep_state(sdiodev->bus)) {
-		brcmf_err("WARN: Write operation when bus is in sleep state\n");
+		brcmf_err("ERROR: Write operation when bus is in sleep state\n");
 	}
 
 	retval = brcmf_sdiod_set_backplane_window(sdiodev, addr);
@@ -315,7 +315,7 @@ static int brcmf_sdiod_skbuff_read(struct brcmf_sdio_dev *sdiodev,
 	int err;
 
 	if (brcmf_sdio_bus_sleep_state(sdiodev->bus)) {
-		brcmf_err("WARN: Read operation when bus is in sleep state\n");
+		brcmf_err("ERROR: Read operation when bus is in sleep state\n");
 	}
 
 	/* Single skb use the standard mmc interface */
@@ -351,7 +351,7 @@ static int brcmf_sdiod_skbuff_write(struct brcmf_sdio_dev *sdiodev,
 	int err;
 
 	if (brcmf_sdio_bus_sleep_state(sdiodev->bus)) {
-		brcmf_err("WARN: Write operation when bus is in sleep state\n");
+		brcmf_err("ERROR: Write operation when bus is in sleep state\n");
 	}
 
 	/* Single skb use the standard mmc interface */
@@ -380,8 +380,8 @@ static int mmc_submit_one(struct mmc_data *md, struct mmc_request *mr,
 	int ret;
 
 	if (brcmf_sdio_bus_sleep_state(sdiodev->bus)) {
-		brcmf_err("WARN: %s operation when bus is in sleep state\n",
-			write ? "Write" : "Read");
+		brcmf_err("ERROR: %s operation when bus is in sleep state\n",
+			  write ? "Write" : "Read");
 	}
 
 	md->sg_len = sg_cnt;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 64f3b21462b7..5ac0a74e963d 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -346,7 +346,7 @@ struct rte_console {
 #define BRCMF_IDLE_INTERVAL	1
 
 #define KSO_WAIT_US 50
-#define KSO_MAX_SEQ_TIME (1000 * 10) /* Ideal time for kso sequence 10ms */
+#define KSO_MAX_SEQ_TIME_NS (1000000 * 10) /* Ideal time for kso sequence 10ms in ns*/
 #define MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US)
 
 static void brcmf_sdio_firmware_callback(struct device *dev, int err,
@@ -570,7 +570,9 @@ struct brcmf_sdio {
 	u32 store_idx;
 	u32 sent_idx;
 	struct task_ctl	thr_rxf_ctl;
-	spinlock_t	rxf_lock; /* lock for rxf idx protection */
+	spinlock_t rxf_lock;	/* lock for rxf idx protection */
+	bool h1_ddr50_mode;	/* H1 DDR50 Mode enabled*/
+	bool ignore_bus_error;	/* Ignore SDIO Bus access error*/
 };
 
 /* clkstate */
@@ -756,8 +758,8 @@ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on)
 	int err = 0;
 	int err_cnt = 0;
 	int try_cnt = 0;
-	unsigned long start_jiffy = 0;
-	unsigned int kso_loop_time = 0;
+	unsigned long kso_loop_time = 0;
+	struct timespec64 ts_start, ts_end, ts_delta;
 
 	brcmf_dbg(TRACE, "Enter: on=%d\n", on);
 
@@ -770,11 +772,14 @@ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on)
 	wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
 
 	/* Start time of kso_sequence */
-	start_jiffy = jiffies;
+	ktime_get_ts64(&ts_start);
 
 	/* Change bus width to 1-bit mode before kso 0 */
 	if (!on && bus->idleclock == BRCMF_IDLE_STOP)
 		brcmf_sdio_set_sdbus_clk_width(bus, SDIO_SDMODE_1BIT);
+	else
+	/* Set Flag to ignore SDIO Bus access error during KSO */
+		bus->ignore_bus_error = true;
 
 	/* 1st KSO write goes to AOS wake up core if device is asleep  */
 	brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
@@ -787,9 +792,7 @@ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on)
 	if (!on) {
 		bus->sdiodev->sbwad_valid = 0;
 		return err;
-	}
-
-	if (on) {
+	} else {
 		/* device WAKEUP through KSO:
 		 * write bit 0 & read back until
 		 * both bits 0 (kso bit) & 1 (dev on status) are set
@@ -797,13 +800,6 @@ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on)
 		cmp_val = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK |
 			  SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK;
 		bmask = cmp_val;
-	} else {
-		/* Put device to sleep, turn off KSO */
-		cmp_val = 0;
-		/* only check for bit0, bit1(dev on status) may not
-		 * get cleared right away
-		 */
-		bmask = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK;
 	}
 
 	do {
@@ -849,24 +845,43 @@ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on)
 
 	} while (try_cnt++ < MAX_KSO_ATTEMPTS);
 
-	kso_loop_time = jiffies_to_usecs(jiffies - start_jiffy);
+	ktime_get_ts64(&ts_end);
+	ts_delta = timespec64_sub(ts_end, ts_start);
+	kso_loop_time = timespec64_to_ns(&ts_delta);
 
 	if (try_cnt > MAX_KSO_ATTEMPTS)
-		brcmf_err("ERR: KSO=%d sequence failed after max tries=%d and err_cnt=%d kso_seq_time=%uus rd_val=0x%x err=%d\n",
-			  on, try_cnt, err_cnt, kso_loop_time, rd_val, err);
-
-	if (kso_loop_time > KSO_MAX_SEQ_TIME)
-		brcmf_dbg(SDIO, "WARN: KSO=%d sequence took %uus > expected %uus try_cnt=%d err_cnt=%d rd_val=0x%x err=%d\n",
-			  on, kso_loop_time, KSO_MAX_SEQ_TIME, try_cnt, err_cnt, rd_val, err);
-	else
-		brcmf_dbg(SDIO, "INFO: KSO=%d try_cnt=%d err_cnt=%d kso_seq_time=%uus rd_val=0x%x err=%d\n",
-			  on, try_cnt, err_cnt, kso_loop_time, rd_val, err);
+		brcmf_err("ERR: KSO=%d sequence failed after max tries=%d and err_cnt=%d\n"
+			  "kso_seq_time=%luns rd_val=0x%x err=%d\n",
+			   on, try_cnt, err_cnt, kso_loop_time, rd_val, err);
 
 	if (on && bus->idleclock == BRCMF_IDLE_STOP) {
 		/* Change the bus width to 4-bit mode on kso 1 */
 		brcmf_sdio_set_sdbus_clk_width(bus, SDIO_SDMODE_4BIT);
+
+		/* New KSO Sequence for H1 DDR50 Mode*/
+		if (bus->h1_ddr50_mode) {
+			struct brcmf_sdio_dev *sdiod = bus->sdiodev;
+			u32 ret, chipid;
+
+			chipid = brcmf_sdiod_readl(sdiod,
+						   bus->ci->ccsec->bus_corebase + SD_REG(chipid),
+						   &ret);
+			brcmf_dbg(SDIO, "chipid: 0x%x ret = 0x%x\n", chipid, ret);
+		}
+
+		/* Clear Flag to ignore SDIO Bus access error during KSO */
+		bus->ignore_bus_error = false;
 		sdio_retune_release(bus->sdiodev->func1);
 	}
+
+	if (kso_loop_time > KSO_MAX_SEQ_TIME_NS)
+		brcmf_err("ERR: KSO=%d sequence took %luns > expected %uns try_cnt=%d\n"
+			  "err_cnt=%d rd_val=0x%x err=%d\n",
+			   on, kso_loop_time, KSO_MAX_SEQ_TIME_NS, try_cnt, err_cnt, rd_val, err);
+
+	brcmf_dbg(SDIO, "INFO: KSO=%d try_cnt=%d err_cnt=%d kso_seq_time=%luns\n"
+			"rd_val=0x%x err=%d\n", on, try_cnt, err_cnt, kso_loop_time, rd_val, err);
+
 	sdio_retune_crc_enable(bus->sdiodev->func1);
 
 	return err;
@@ -1240,7 +1255,7 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok)
 
 bool brcmf_sdio_bus_sleep_state(struct brcmf_sdio *bus)
 {
-	return bus->sleeping;
+	return bus->sleeping && !bus->ignore_bus_error;
 }
 
 #ifdef DEBUG
@@ -4879,6 +4894,20 @@ brcmf_sdio_buscore_sec_attach(void *ctx, struct brcmf_blhs **blhs, struct brcmf_
 		*ccsec = ccsech;
 	}
 
+	if (cardcap & SDIO_CCCR_BRCM_CARDCAP_CHIPID_PRESENT) {
+		u32 reg_val;
+		u32 err;
+
+		/* Get SDIO Bus Mode*/
+		reg_val = brcmf_sdiod_func0_rb(sdiodev, SDIO_CCCR_SPEED, &err);
+		if (err) {
+			brcmf_err("error getting sdio bus speed\n");
+		} else {
+			if (reg_val & SDIO_SPEED_DDR50)
+				sdiodev->bus->h1_ddr50_mode = true;
+		}
+	}
+
 	return 0;
 }
 
@@ -5725,8 +5754,6 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
 	else
 		bus->idletime = BRCMF_IDLE_INTERVAL;
 
-	bus->idleclock = BRCMF_IDLE_ACTIVE;
-
 	/* SR state */
 	bus->sr_enabled = false;
 
-- 
2.25.1

