aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorArend van Spriel <arend@broadcom.com>2014-01-13 16:20:25 -0500
committerJohn W. Linville <linville@tuxdriver.com>2014-01-16 14:55:21 -0500
commit3355650c61c4e3d56deadb601762b09ed8a30939 (patch)
treeb82679b9c072575609eef263070e0d61c550db48 /drivers/net/wireless
parent53036261033abdab7323a4a896a9bde84d2c2f17 (diff)
brcmfmac: rework firmware download code
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@broadcom.com> Reviewed-by: Hante Meuleman <meuleman@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c87
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c11
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h2
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 19057896d92e..b9d5f735a71b 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)
3192 return rxlen ? (int)rxlen : -ETIMEDOUT; 3192 return rxlen ? (int)rxlen : -ETIMEDOUT;
3193} 3193}
3194 3194
3195static bool brcmf_sdio_download_state(struct brcmf_sdio *bus, bool enter)
3196{
3197 struct chip_info *ci = bus->ci;
3198
3199 /* To enter download state, disable ARM and reset SOCRAM.
3200 * To exit download state, simply reset ARM (default is RAM boot).
3201 */
3202 if (enter) {
3203 bus->alp_only = true;
3204
3205 brcmf_sdio_chip_enter_download(bus->sdiodev, ci);
3206 } else {
3207 if (!brcmf_sdio_chip_exit_download(bus->sdiodev, ci))
3208 return false;
3209
3210 /* Allow HT Clock now that the ARM is running. */
3211 bus->alp_only = false;
3212
3213 bus->sdiodev->bus_if->state = BRCMF_BUS_LOAD;
3214 }
3215
3216 return true;
3217}
3218
3219#ifdef DEBUG 3195#ifdef DEBUG
3220static bool 3196static bool
3221brcmf_sdio_verifymemory(struct brcmf_sdio_dev *sdiodev, u32 ram_addr, 3197brcmf_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,
3270} 3246}
3271#endif /* DEBUG */ 3247#endif /* DEBUG */
3272 3248
3273static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus) 3249static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus,
3250 const struct firmware *fw)
3274{ 3251{
3275 const struct firmware *fw;
3276 int err; 3252 int err;
3277 int offset; 3253 int offset;
3278 int address; 3254 int address;
@@ -3280,14 +3256,6 @@ static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus)
3280 3256
3281 brcmf_dbg(TRACE, "Enter\n"); 3257 brcmf_dbg(TRACE, "Enter\n");
3282 3258
3283 fw = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_BIN);
3284 if (fw == NULL)
3285 return -ENOENT;
3286
3287 if (brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_ARM_CR4) !=
3288 BRCMF_MAX_CORENUM)
3289 memcpy(&bus->ci->rst_vec, fw->data, sizeof(bus->ci->rst_vec));
3290
3291 err = 0; 3259 err = 0;
3292 offset = 0; 3260 offset = 0;
3293 address = bus->ci->rambase; 3261 address = bus->ci->rambase;
@@ -3299,7 +3267,7 @@ static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus)
3299 if (err) { 3267 if (err) {
3300 brcmf_err("error %d on writing %d membytes at 0x%08x\n", 3268 brcmf_err("error %d on writing %d membytes at 0x%08x\n",
3301 err, len, address); 3269 err, len, address);
3302 goto failure; 3270 return err;
3303 } 3271 }
3304 offset += len; 3272 offset += len;
3305 address += len; 3273 address += len;
@@ -3309,15 +3277,12 @@ static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus)
3309 (u8 *)fw->data, fw->size)) 3277 (u8 *)fw->data, fw->size))
3310 err = -EIO; 3278 err = -EIO;
3311 3279
3312failure:
3313 release_firmware(fw);
3314
3315 return err; 3280 return err;
3316} 3281}
3317 3282
3318static int brcmf_sdio_download_nvram(struct brcmf_sdio *bus) 3283static int brcmf_sdio_download_nvram(struct brcmf_sdio *bus,
3284 const struct firmware *nv)
3319{ 3285{
3320 const struct firmware *nv;
3321 void *vars; 3286 void *vars;
3322 u32 varsz; 3287 u32 varsz;
3323 int address; 3288 int address;
@@ -3325,12 +3290,7 @@ static int brcmf_sdio_download_nvram(struct brcmf_sdio *bus)
3325 3290
3326 brcmf_dbg(TRACE, "Enter\n"); 3291 brcmf_dbg(TRACE, "Enter\n");
3327 3292
3328 nv = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_NVRAM);
3329 if (nv == NULL)
3330 return -ENOENT;
3331
3332 vars = brcmf_nvram_strip(nv, &varsz); 3293 vars = brcmf_nvram_strip(nv, &varsz);
3333 release_firmware(nv);
3334 3294
3335 if (vars == NULL) 3295 if (vars == NULL)
3336 return -EINVAL; 3296 return -EINVAL;
@@ -3351,33 +3311,52 @@ static int brcmf_sdio_download_nvram(struct brcmf_sdio *bus)
3351static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus) 3311static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus)
3352{ 3312{
3353 int bcmerror = -EFAULT; 3313 int bcmerror = -EFAULT;
3354 3314 const struct firmware *fw;
3315 u32 rstvec;
3355 3316
3356 sdio_claim_host(bus->sdiodev->func[1]); 3317 sdio_claim_host(bus->sdiodev->func[1]);
3357 brcmf_sdio_clkctl(bus, CLK_AVAIL, false); 3318 brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
3358 3319
3359 /* Keep arm in reset */ 3320 /* Keep arm in reset */
3360 if (!brcmf_sdio_download_state(bus, true)) { 3321 brcmf_sdio_chip_enter_download(bus->sdiodev, bus->ci);
3361 brcmf_err("error placing ARM core in reset\n"); 3322
3323 fw = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_BIN);
3324 if (fw == NULL) {
3325 bcmerror = -ENOENT;
3362 goto err; 3326 goto err;
3363 } 3327 }
3364 3328
3365 if (brcmf_sdio_download_code_file(bus)) { 3329 rstvec = get_unaligned_le32(fw->data);
3330 brcmf_dbg(SDIO, "firmware rstvec: %x\n", rstvec);
3331
3332 bcmerror = brcmf_sdio_download_code_file(bus, fw);
3333 release_firmware(fw);
3334 if (bcmerror) {
3366 brcmf_err("dongle image file download failed\n"); 3335 brcmf_err("dongle image file download failed\n");
3367 goto err; 3336 goto err;
3368 } 3337 }
3369 3338
3370 if (brcmf_sdio_download_nvram(bus)) { 3339 fw = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_NVRAM);
3340 if (fw == NULL) {
3341 bcmerror = -ENOENT;
3342 goto err;
3343 }
3344
3345 bcmerror = brcmf_sdio_download_nvram(bus, fw);
3346 release_firmware(fw);
3347 if (bcmerror) {
3371 brcmf_err("dongle nvram file download failed\n"); 3348 brcmf_err("dongle nvram file download failed\n");
3372 goto err; 3349 goto err;
3373 } 3350 }
3374 3351
3375 /* Take arm out of reset */ 3352 /* Take arm out of reset */
3376 if (!brcmf_sdio_download_state(bus, false)) { 3353 if (!brcmf_sdio_chip_exit_download(bus->sdiodev, bus->ci, rstvec)) {
3377 brcmf_err("error getting out of ARM core reset\n"); 3354 brcmf_err("error getting out of ARM core reset\n");
3378 goto err; 3355 goto err;
3379 } 3356 }
3380 3357
3358 /* Allow HT Clock now that the ARM is running. */
3359 bus->sdiodev->bus_if->state = BRCMF_BUS_LOAD;
3381 bcmerror = 0; 3360 bcmerror = 0;
3382 3361
3383err: 3362err:
@@ -3566,9 +3545,11 @@ static int brcmf_sdio_bus_init(struct device *dev)
3566 3545
3567 /* try to download image and nvram to the dongle */ 3546 /* try to download image and nvram to the dongle */
3568 if (bus_if->state == BRCMF_BUS_DOWN) { 3547 if (bus_if->state == BRCMF_BUS_DOWN) {
3548 bus->alp_only = true;
3569 err = brcmf_sdio_download_firmware(bus); 3549 err = brcmf_sdio_download_firmware(bus);
3570 if (err) 3550 if (err)
3571 return err; 3551 return err;
3552 bus->alp_only = false;
3572 } 3553 }
3573 3554
3574 if (!bus->sdiodev->bus_if->drvr) 3555 if (!bus->sdiodev->bus_if->drvr)
@@ -3778,8 +3759,6 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
3778 u32 reg_val; 3759 u32 reg_val;
3779 u32 drivestrength; 3760 u32 drivestrength;
3780 3761
3781 bus->alp_only = true;
3782
3783 sdio_claim_host(bus->sdiodev->func[1]); 3762 sdio_claim_host(bus->sdiodev->func[1]);
3784 3763
3785 pr_debug("F1 signature read @0x18000000=0x%4x\n", 3764 pr_debug("F1 signature read @0x18000000=0x%4x\n",
@@ -4088,7 +4067,7 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus)
4088 * essentially resets all necessary cores 4067 * essentially resets all necessary cores
4089 */ 4068 */
4090 msleep(20); 4069 msleep(20);
4091 brcmf_sdio_download_state(bus, true); 4070 brcmf_sdio_chip_enter_download(bus->sdiodev, bus->ci);
4092 brcmf_sdio_clkctl(bus, CLK_NONE, false); 4071 brcmf_sdio_clkctl(bus, CLK_NONE, false);
4093 sdio_release_host(bus->sdiodev->func[1]); 4072 sdio_release_host(bus->sdiodev->func[1]);
4094 brcmf_sdio_chip_detach(&bus->ci); 4073 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 434297648e34..88eacf16211a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
@@ -923,7 +923,8 @@ brcmf_sdio_chip_cr4_enterdl(struct brcmf_sdio_dev *sdiodev,
923} 923}
924 924
925static bool 925static bool
926brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci) 926brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
927 u32 rstvec)
927{ 928{
928 u8 core_idx; 929 u8 core_idx;
929 u32 reg_addr; 930 u32 reg_addr;
@@ -935,8 +936,8 @@ brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci)
935 brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL); 936 brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
936 937
937 /* Write reset vector to address 0 */ 938 /* Write reset vector to address 0 */
938 brcmf_sdiod_ramrw(sdiodev, true, 0, (void *)&ci->rst_vec, 939 brcmf_sdiod_ramrw(sdiodev, true, 0, (void *)&rstvec,
939 sizeof(ci->rst_vec)); 940 sizeof(rstvec));
940 941
941 /* restore ARM */ 942 /* restore ARM */
942 ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, ARMCR4_BCMA_IOCTL_CPUHALT, 943 ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, ARMCR4_BCMA_IOCTL_CPUHALT,
@@ -960,7 +961,7 @@ void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
960} 961}
961 962
962bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev, 963bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
963 struct chip_info *ci) 964 struct chip_info *ci, u32 rstvec)
964{ 965{
965 u8 arm_core_idx; 966 u8 arm_core_idx;
966 967
@@ -968,5 +969,5 @@ bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
968 if (BRCMF_MAX_CORENUM != arm_core_idx) 969 if (BRCMF_MAX_CORENUM != arm_core_idx)
969 return brcmf_sdio_chip_cm3_exitdl(sdiodev, ci); 970 return brcmf_sdio_chip_cm3_exitdl(sdiodev, ci);
970 971
971 return brcmf_sdio_chip_cr4_exitdl(sdiodev, ci); 972 return brcmf_sdio_chip_cr4_exitdl(sdiodev, ci, rstvec);
972} 973}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
index 91c61cb9de87..9a72b71f5259 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);
226void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev, 226void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
227 struct chip_info *ci); 227 struct chip_info *ci);
228bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev, 228bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
229 struct chip_info *ci); 229 struct chip_info *ci, u32 rstvec);
230 230
231#endif /* _BRCMFMAC_SDIO_CHIP_H_ */ 231#endif /* _BRCMFMAC_SDIO_CHIP_H_ */