Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}