Search Linux Wireless

[PATCH 4/8] brcmfmac: rework firmware download code

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The firmware download code has been restructured so the reset vector
does not need to be stored in a structure, but keep it on the stack
to be passed to exit download function.

Reviewed-by: Franky Lin <frankyl@xxxxxxxxxxxx>
Reviewed-by: Hante Meuleman <meuleman@xxxxxxxxxxxx>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@xxxxxxxxxxxx>
Reviewed-by: Daniel (Deognyoun) Kim <dekim@xxxxxxxxxxxx>
Signed-off-by: Arend van Spriel <arend@xxxxxxxxxxxx>
---
 drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c |   87 ++++++++------------
 .../net/wireless/brcm80211/brcmfmac/sdio_chip.c    |   11 +--
 .../net/wireless/brcm80211/brcmfmac/sdio_chip.h    |    2 +-
 3 files changed, 40 insertions(+), 60 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 1905789..b9d5f73 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -3192,30 +3192,6 @@ brcmf_sdio_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
 	return rxlen ? (int)rxlen : -ETIMEDOUT;
 }
 
-static bool brcmf_sdio_download_state(struct brcmf_sdio *bus, bool enter)
-{
-	struct chip_info *ci = bus->ci;
-
-	/* To enter download state, disable ARM and reset SOCRAM.
-	 * To exit download state, simply reset ARM (default is RAM boot).
-	 */
-	if (enter) {
-		bus->alp_only = true;
-
-		brcmf_sdio_chip_enter_download(bus->sdiodev, ci);
-	} else {
-		if (!brcmf_sdio_chip_exit_download(bus->sdiodev, ci))
-			return false;
-
-		/* Allow HT Clock now that the ARM is running. */
-		bus->alp_only = false;
-
-		bus->sdiodev->bus_if->state = BRCMF_BUS_LOAD;
-	}
-
-	return true;
-}
-
 #ifdef DEBUG
 static bool
 brcmf_sdio_verifymemory(struct brcmf_sdio_dev *sdiodev, u32 ram_addr,
@@ -3270,9 +3246,9 @@ brcmf_sdio_verifymemory(struct brcmf_sdio_dev *sdiodev, u32 ram_addr,
 }
 #endif	/* DEBUG */
 
-static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus)
+static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus,
+					 const struct firmware *fw)
 {
-	const struct firmware *fw;
 	int err;
 	int offset;
 	int address;
@@ -3280,14 +3256,6 @@ static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus)
 
 	brcmf_dbg(TRACE, "Enter\n");
 
-	fw = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_BIN);
-	if (fw == NULL)
-		return -ENOENT;
-
-	if (brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_ARM_CR4) !=
-	    BRCMF_MAX_CORENUM)
-		memcpy(&bus->ci->rst_vec, fw->data, sizeof(bus->ci->rst_vec));
-
 	err = 0;
 	offset = 0;
 	address = bus->ci->rambase;
@@ -3299,7 +3267,7 @@ static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus)
 		if (err) {
 			brcmf_err("error %d on writing %d membytes at 0x%08x\n",
 				  err, len, address);
-			goto failure;
+			return err;
 		}
 		offset += len;
 		address += len;
@@ -3309,15 +3277,12 @@ static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus)
 					     (u8 *)fw->data, fw->size))
 			err = -EIO;
 
-failure:
-	release_firmware(fw);
-
 	return err;
 }
 
-static int brcmf_sdio_download_nvram(struct brcmf_sdio *bus)
+static int brcmf_sdio_download_nvram(struct brcmf_sdio *bus,
+				     const struct firmware *nv)
 {
-	const struct firmware *nv;
 	void *vars;
 	u32 varsz;
 	int address;
@@ -3325,12 +3290,7 @@ static int brcmf_sdio_download_nvram(struct brcmf_sdio *bus)
 
 	brcmf_dbg(TRACE, "Enter\n");
 
-	nv = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_NVRAM);
-	if (nv == NULL)
-		return -ENOENT;
-
 	vars = brcmf_nvram_strip(nv, &varsz);
-	release_firmware(nv);
 
 	if (vars == NULL)
 		return -EINVAL;
@@ -3351,33 +3311,52 @@ static int brcmf_sdio_download_nvram(struct brcmf_sdio *bus)
 static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus)
 {
 	int bcmerror = -EFAULT;
-
+	const struct firmware *fw;
+	u32 rstvec;
 
 	sdio_claim_host(bus->sdiodev->func[1]);
 	brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
 
 	/* Keep arm in reset */
-	if (!brcmf_sdio_download_state(bus, true)) {
-		brcmf_err("error placing ARM core in reset\n");
+	brcmf_sdio_chip_enter_download(bus->sdiodev, bus->ci);
+
+	fw = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_BIN);
+	if (fw == NULL) {
+		bcmerror = -ENOENT;
 		goto err;
 	}
 
-	if (brcmf_sdio_download_code_file(bus)) {
+	rstvec = get_unaligned_le32(fw->data);
+	brcmf_dbg(SDIO, "firmware rstvec: %x\n", rstvec);
+
+	bcmerror = brcmf_sdio_download_code_file(bus, fw);
+	release_firmware(fw);
+	if (bcmerror) {
 		brcmf_err("dongle image file download failed\n");
 		goto err;
 	}
 
-	if (brcmf_sdio_download_nvram(bus)) {
+	fw = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_NVRAM);
+	if (fw == NULL) {
+		bcmerror = -ENOENT;
+		goto err;
+	}
+
+	bcmerror = brcmf_sdio_download_nvram(bus, fw);
+	release_firmware(fw);
+	if (bcmerror) {
 		brcmf_err("dongle nvram file download failed\n");
 		goto err;
 	}
 
 	/* Take arm out of reset */
-	if (!brcmf_sdio_download_state(bus, false)) {
+	if (!brcmf_sdio_chip_exit_download(bus->sdiodev, bus->ci, rstvec)) {
 		brcmf_err("error getting out of ARM core reset\n");
 		goto err;
 	}
 
+	/* Allow HT Clock now that the ARM is running. */
+	bus->sdiodev->bus_if->state = BRCMF_BUS_LOAD;
 	bcmerror = 0;
 
 err:
@@ -3566,9 +3545,11 @@ static int brcmf_sdio_bus_init(struct device *dev)
 
 	/* try to download image and nvram to the dongle */
 	if (bus_if->state == BRCMF_BUS_DOWN) {
+		bus->alp_only = true;
 		err = brcmf_sdio_download_firmware(bus);
 		if (err)
 			return err;
+		bus->alp_only = false;
 	}
 
 	if (!bus->sdiodev->bus_if->drvr)
@@ -3778,8 +3759,6 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
 	u32 reg_val;
 	u32 drivestrength;
 
-	bus->alp_only = true;
-
 	sdio_claim_host(bus->sdiodev->func[1]);
 
 	pr_debug("F1 signature read @0x18000000=0x%4x\n",
@@ -4088,7 +4067,7 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus)
 			 * essentially resets all necessary cores
 			 */
 			msleep(20);
-			brcmf_sdio_download_state(bus, true);
+			brcmf_sdio_chip_enter_download(bus->sdiodev, bus->ci);
 			brcmf_sdio_clkctl(bus, CLK_NONE, false);
 			sdio_release_host(bus->sdiodev->func[1]);
 			brcmf_sdio_chip_detach(&bus->ci);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
index a002af9..909d720 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
@@ -917,7 +917,8 @@ brcmf_sdio_chip_cr4_enterdl(struct brcmf_sdio_dev *sdiodev,
 }
 
 static bool
-brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci)
+brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
+			   u32 rstvec)
 {
 	u8 core_idx;
 	u32 reg_addr;
@@ -929,8 +930,8 @@ brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci)
 	brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
 
 	/* Write reset vector to address 0 */
-	brcmf_sdiod_ramrw(sdiodev, true, 0, (void *)&ci->rst_vec,
-			  sizeof(ci->rst_vec));
+	brcmf_sdiod_ramrw(sdiodev, true, 0, (void *)&rstvec,
+			  sizeof(rstvec));
 
 	/* restore ARM */
 	ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, BCMA_IOCTL_ARMCR4_HALT,
@@ -954,7 +955,7 @@ void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
 }
 
 bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
-				   struct chip_info *ci)
+				   struct chip_info *ci, u32 rstvec)
 {
 	u8 arm_core_idx;
 
@@ -962,5 +963,5 @@ bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
 	if (BRCMF_MAX_CORENUM != arm_core_idx)
 		return brcmf_sdio_chip_cm3_exitdl(sdiodev, ci);
 
-	return brcmf_sdio_chip_cr4_exitdl(sdiodev, ci);
+	return brcmf_sdio_chip_cr4_exitdl(sdiodev, ci, rstvec);
 }
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
index 91c61cb..9a72b71 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
@@ -226,6 +226,6 @@ u8 brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid);
 void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
 				    struct chip_info *ci);
 bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
-				   struct chip_info *ci);
+				   struct chip_info *ci, u32 rstvec);
 
 #endif		/* _BRCMFMAC_SDIO_CHIP_H_ */
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux