From 4f2e7a1ea21d457fdb0fbbb5754b54e2c10a05fb Mon Sep 17 00:00:00 2001
From: Owen Huang <Owen.Huang@infineon.com>
Date: Fri, 24 Feb 2023 00:04:13 -0600
Subject: [PATCH 217/296] non-upstream: btsdio: claim function 3 in-band irq

1. claim function 3 irq
2. sdmmc driver call _btsdio_int_handler() while F3 irq happened
3. FMAC driver call BT registered callback function
4. BT driver trigger thread to handle irq

P.S. set drvdata for function 3 when chip support F3 only


Signed-off-by: Owen Huang <Owen.Huang@infineon.com>


Signed-off-by: Shelley Yang <shelley.yang@infineon.com>
---
 .../broadcom/brcm80211/brcmfmac/bcmsdh.c      |  5 ++-
 .../brcm80211/brcmfmac/bt_shared_sdio_ifx.c   | 42 +++++++++++++++++--
 .../brcm80211/brcmfmac/bt_shared_sdio_ifx.h   |  1 -
 3 files changed, 41 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index eac9f2a666f0..ca3c0ddeabbb 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -83,12 +83,13 @@ static irqreturn_t brcmf_sdiod_oob_irqhandler(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+/* interrupt handler for SDIO function 1 interrupt */
 static void brcmf_sdiod_ib_irqhandler(struct sdio_func *func)
 {
 	struct brcmf_bus *bus_if = dev_get_drvdata(&func->dev);
 	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
 
-	brcmf_dbg(INTR, "IB intr triggered\n");
+	brcmf_dbg(INTR, "F%d IB intr triggered\n", func->num);
 
 	brcmf_sdio_isr(sdiodev->bus, false);
 }
@@ -1132,7 +1133,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
 	func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
 
 	/* Consume func num 1 but dont do anything with it. */
-	if (func->num == SDIO_FUNC_1)
+	if (func->num == SDIO_FUNC_1 || func->num == SDIO_FUNC_3)
 		return 0;
 
 	/* Ignore anything but func 2 */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bt_shared_sdio_ifx.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bt_shared_sdio_ifx.c
index 0d50f626f2c9..bab98396f853 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bt_shared_sdio_ifx.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bt_shared_sdio_ifx.c
@@ -441,19 +441,29 @@ static void *inf_btsdio_get_func_entity(struct brcmf_sdio_dev *sdiodev, u8 fn)
 	return func;
 }
 
-void inf_btsdio_int_handler(struct brcmf_bus *bus_if)
+static void _btsdio_int_handler(struct sdio_func *func)
 {
+	struct brcmf_bus *bus_if = NULL;
+	struct brcmf_sdio_dev *sdiodev = NULL;
 	struct inf_bt_if *bt_if = NULL;
 
+	if (!func) {
+		brcmf_err("func is null\n");
+		return;
+	}
+	bus_if = dev_get_drvdata(&func->dev);
+
 	if (!bus_if) {
 		brcmf_err("bus_if is null\n");
 		return;
 	}
+	sdiodev = bus_if->bus_priv.sdio;
+	bt_if = bus_if->bt_if;
 
 	if (!bus_if->bt_if)
 		return;
 
-	bt_if = bus_if->bt_if;
+	brcmf_dbg(INTR, "F%d IB intr triggered\n", func->num);
 
 	if (bt_if->bt_sdio_int_cb)
 		bt_if->bt_sdio_int_cb(bt_if->bt_data);
@@ -950,6 +960,7 @@ void inf_btsdio_init(struct brcmf_bus *bus_if)
 {
 	struct brcmf_sdio_dev *sdiodev = NULL;
 	struct inf_bt_if *bt_if = NULL;
+	struct brcmfmac_sdio_pd *pdata = NULL;
 
 	brcmf_dbg(INFO, "Enter\n");
 
@@ -958,6 +969,7 @@ void inf_btsdio_init(struct brcmf_bus *bus_if)
 		return;
 	}
 	sdiodev = bus_if->bus_priv.sdio;
+	pdata = &sdiodev->settings->bus.sdio;
 
 	if (!inf_btsdio_is_over_sdio(bus_if)) {
 		brcmf_err("bt over uart\n");
@@ -982,8 +994,15 @@ void inf_btsdio_init(struct brcmf_bus *bus_if)
 	if (sdiodev->func1->device == SDIO_DEVICE_ID_CYPRESS_55500)
 		bt_if->set_bt_reset = true;
 
-	// wait for next commit for F3 interrupt
-	//brcmf_sdiod_intr_register_f3(sdiodev);
+	sdio_claim_host(sdiodev->func1);
+	/* drvdata used for irqhandler */
+	dev_set_drvdata(&sdiodev->func3->dev, bus_if);
+	/* register interrupt */
+	if (!pdata->oob_irq_supported) {
+		brcmf_dbg(INFO, "register F3 ib irq\n");
+		sdio_claim_irq(sdiodev->func3, _btsdio_int_handler);
+	}
+	sdio_release_host(sdiodev->func1);
 
 	brcmf_dbg(INFO, "init version (%d.%d.%d) done\n",
 		  BTS_VER_MAJOR, BTS_VER_MINOR, BTS_VER_PATCH);
@@ -991,6 +1010,9 @@ void inf_btsdio_init(struct brcmf_bus *bus_if)
 
 void inf_btsdio_deinit(struct brcmf_bus *bus_if)
 {
+	struct brcmf_sdio_dev *sdiodev = NULL;
+	struct brcmfmac_sdio_pd *pdata = NULL;
+
 	brcmf_dbg(INFO, "Enter\n");
 
 	if (!bus_if) {
@@ -1001,6 +1023,18 @@ void inf_btsdio_deinit(struct brcmf_bus *bus_if)
 	if (!bus_if->bt_if)
 		return;
 
+	sdiodev = bus_if->bus_priv.sdio;
+	pdata = &sdiodev->settings->bus.sdio;
+
+	/* unregister interrupt */
+	sdio_claim_host(sdiodev->func1);
+	if (!pdata->oob_irq_supported) {
+		brcmf_dbg(INFO, "release F3 ib irq\n");
+		sdio_release_irq(sdiodev->func3);
+	}
+	dev_set_drvdata(&sdiodev->func3->dev, NULL);
+	sdio_release_host(sdiodev->func1);
+
 	inf_bus_detach(bus_if);
 
 	/* Free all error info */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bt_shared_sdio_ifx.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bt_shared_sdio_ifx.h
index 921e82f518d5..25537aea7817 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bt_shared_sdio_ifx.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bt_shared_sdio_ifx.h
@@ -36,7 +36,6 @@
 
 void inf_btsdio_init(struct brcmf_bus *bus_if);
 void inf_btsdio_deinit(struct brcmf_bus *bus_if);
-void inf_btsdio_int_handler(struct brcmf_bus *bus_if);
 bool inf_btsdio_is_active(struct brcmf_bus *bus_if);
 bool inf_btsdio_set_bt_reset(struct brcmf_bus *bus_if);
 bool inf_btsdio_inited(struct brcmf_bus *bus_if);
-- 
2.25.1

