diff options
author | Arend van Spriel <arend@broadcom.com> | 2014-01-13 16:20:25 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-01-16 14:55:21 -0500 |
commit | 3355650c61c4e3d56deadb601762b09ed8a30939 (patch) | |
tree | b82679b9c072575609eef263070e0d61c550db48 /drivers/net/wireless | |
parent | 53036261033abdab7323a4a896a9bde84d2c2f17 (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.c | 87 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c | 11 | ||||
-rw-r--r-- | drivers/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 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 | ||
3195 | static 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 |
3220 | static bool | 3196 | static bool |
3221 | brcmf_sdio_verifymemory(struct brcmf_sdio_dev *sdiodev, u32 ram_addr, | 3197 | 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, | |||
3270 | } | 3246 | } |
3271 | #endif /* DEBUG */ | 3247 | #endif /* DEBUG */ |
3272 | 3248 | ||
3273 | static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus) | 3249 | static 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 | ||
3312 | failure: | ||
3313 | release_firmware(fw); | ||
3314 | |||
3315 | return err; | 3280 | return err; |
3316 | } | 3281 | } |
3317 | 3282 | ||
3318 | static int brcmf_sdio_download_nvram(struct brcmf_sdio *bus) | 3283 | static 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) | |||
3351 | static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus) | 3311 | static 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 | ||
3383 | err: | 3362 | err: |
@@ -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 | ||
925 | static bool | 925 | static bool |
926 | brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci) | 926 | brcmf_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 | ||
962 | bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev, | 963 | bool 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); | |||
226 | void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev, | 226 | void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev, |
227 | struct chip_info *ci); | 227 | struct chip_info *ci); |
228 | bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev, | 228 | bool 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_ */ |