static int ks7010_upload_firmware(struct ks_sdio_card *card) { struct ks_wlan_private *priv = card->priv; unsigned int size, offset, n = 0; unsigned char *rom_buf; unsigned char byte = 0; int ret; unsigned int length; const struct firmware *fw_entry = NULL; rom_buf = kmalloc(ROM_BUFF_SIZE, GFP_KERNEL); if (!rom_buf) return -ENOMEM; sdio_claim_host(card->func); /* Firmware running ? */ ret = ks7010_sdio_readb(priv, GCR_A, &byte); if (byte == GCR_A_RUN) { DPRINTK(0, "MAC firmware running ...\n"); goto release_host_and_free; } ret = request_firmware(&fw_entry, ROM_FILE, &priv->ks_sdio_card->func->dev); if (ret) goto release_host_and_free; length = fw_entry->size; n = 0; do { if (length >= ROM_BUFF_SIZE) { size = ROM_BUFF_SIZE; length = length - ROM_BUFF_SIZE; } else { size = length; length = 0; } DPRINTK(4, "size = %d\n", size); if (size == 0) break; memcpy(rom_buf, fw_entry->data + n, size); offset = n; ret = ks7010_sdio_update_index(priv, KS7010_IRAM_ADDRESS + offset); if (ret) goto release_firmware; ret = ks7010_sdio_write(priv, DATA_WINDOW, rom_buf, size); if (ret) goto release_firmware; ret = ks7010_sdio_data_compare(priv, DATA_WINDOW, rom_buf, size); if (ret) goto release_firmware; n += size; } while (size); ret = ks7010_sdio_writeb(priv, GCR_A, GCR_A_REMAP); if (ret) goto release_firmware; DPRINTK(4, " REMAP Request : GCR_A\n"); /* Firmware running check */ for (n = 0; n < 50; ++n) { mdelay(10); /* wait_ms(10); */ ret = ks7010_sdio_readb(priv, GCR_A, &byte); if (ret) goto release_firmware; if (byte == GCR_A_RUN) break; } DPRINTK(4, "firmware wakeup (%d)!!!!\n", n); if ((50) <= n) { DPRINTK(1, "firmware can't start\n"); ret = -EIO; goto release_firmware; } ret = 0; release_firmware: release_firmware(fw_entry); release_host_and_free: sdio_release_host(card->func); kfree(rom_buf); return ret; }
static int ks7010_upload_firmware(struct ks_wlan_private *priv, struct ks_sdio_card *card) { unsigned int size, offset, n = 0; unsigned char *rom_buf; unsigned char rw_data = 0; int retval, rc = 0; int length; const struct firmware *fw_entry = NULL; rom_buf = NULL; /* buffer allocate */ rom_buf = kmalloc(ROM_BUFF_SIZE, GFP_KERNEL); if (!rom_buf) { rc = 3; goto error_out0; } sdio_claim_host(card->func); /* Firmware running ? */ retval = ks7010_sdio_read(priv, GCR_A, &rw_data, sizeof(rw_data)); if (rw_data == GCR_A_RUN) { DPRINTK(0, "MAC firmware running ...\n"); rc = 0; goto error_out0; } retval = request_firmware(&fw_entry, ROM_FILE, &priv->ks_wlan_hw.sdio_card->func->dev); if (retval) return retval; length = fw_entry->size; /* Load Program */ n = 0; do { if (length >= ROM_BUFF_SIZE) { size = ROM_BUFF_SIZE; length = length - ROM_BUFF_SIZE; } else { size = length; length = 0; } DPRINTK(4, "size = %d\n", size); if (size == 0) break; memcpy(rom_buf, fw_entry->data + n, size); /* Update write index */ offset = n; retval = ks7010_sdio_update_index(priv, KS7010_IRAM_ADDRESS + offset); if (retval) { rc = 6; goto error_out1; } /* Write data */ retval = ks7010_sdio_write(priv, DATA_WINDOW, rom_buf, size); if (retval) { rc = 8; goto error_out1; } /* compare */ retval = ks7010_sdio_data_compare(priv, DATA_WINDOW, rom_buf, size); if (retval) { rc = 9; goto error_out1; } n += size; } while (size); /* Remap request */ rw_data = GCR_A_REMAP; retval = ks7010_sdio_write(priv, GCR_A, &rw_data, sizeof(rw_data)); if (retval) { rc = 11; goto error_out1; } DPRINTK(4, " REMAP Request : GCR_A=%02X\n", rw_data); /* Firmware running check */ for (n = 0; n < 50; ++n) { mdelay(10); /* wait_ms(10); */ retval = ks7010_sdio_read(priv, GCR_A, &rw_data, sizeof(rw_data)); if (retval) { rc = 11; goto error_out1; } if (rw_data == GCR_A_RUN) break; } DPRINTK(4, "firmware wakeup (%d)!!!!\n", n); if ((50) <= n) { DPRINTK(1, "firmware can't start\n"); rc = 12; goto error_out1; } rc = 0; error_out1: release_firmware(fw_entry); error_out0: sdio_release_host(card->func); if (rom_buf) kfree(rom_buf); return rc; }