Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 962ee1b1 authored by Alex Dubov's avatar Alex Dubov Committed by Linus Torvalds
Browse files

memstick: add support for 8-bit parallel mode



Newer MemoryStick (HG) cards and hosts support 8-bit parallel mode of
operation in addition to original 4-bit and 1-bit modes.

Signed-off-by: default avatarAlex Dubov <oakad@yahoo.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent ead70773
Loading
Loading
Loading
Loading
+55 −26
Original line number Original line Diff line number Diff line
@@ -816,12 +816,13 @@ static int mspro_block_wait_for_ced(struct memstick_dev *card)
	return card->current_mrq.error;
	return card->current_mrq.error;
}
}


static int mspro_block_switch_to_parallel(struct memstick_dev *card)
static int mspro_block_set_interface(struct memstick_dev *card,
				     unsigned char sys_reg)
{
{
	struct memstick_host *host = card->host;
	struct memstick_host *host = card->host;
	struct mspro_block_data *msb = memstick_get_drvdata(card);
	struct mspro_block_data *msb = memstick_get_drvdata(card);
	struct mspro_param_register param = {
	struct mspro_param_register param = {
		.system = MEMSTICK_SYS_PAR4,
		.system = sys_reg,
		.data_count = 0,
		.data_count = 0,
		.data_address = 0,
		.data_address = 0,
		.tpc_param = 0
		.tpc_param = 0
@@ -833,41 +834,70 @@ static int mspro_block_switch_to_parallel(struct memstick_dev *card)
			  sizeof(param));
			  sizeof(param));
	memstick_new_req(host);
	memstick_new_req(host);
	wait_for_completion(&card->mrq_complete);
	wait_for_completion(&card->mrq_complete);
	if (card->current_mrq.error)
	return card->current_mrq.error;
	return card->current_mrq.error;
}

static int mspro_block_switch_interface(struct memstick_dev *card)
{
	struct memstick_host *host = card->host;
	struct mspro_block_data *msb = memstick_get_drvdata(card);
	int rc = 0;

	if (msb->caps & MEMSTICK_CAP_PAR4)
		rc = mspro_block_set_interface(card, MEMSTICK_SYS_PAR4);
	else
		return 0;

	if (rc) {
		printk(KERN_WARNING
		       "%s: could not switch to 4-bit mode, error %d\n",
		       card->dev.bus_id, rc);
		return 0;
	}


	msb->system = MEMSTICK_SYS_PAR4;
	msb->system = MEMSTICK_SYS_PAR4;
	host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PAR4);
	host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PAR4);
	printk(KERN_INFO "%s: switching to 4-bit parallel mode\n",
	       card->dev.bus_id);

	if (msb->caps & MEMSTICK_CAP_PAR8) {
		rc = mspro_block_set_interface(card, MEMSTICK_SYS_PAR8);

		if (!rc) {
			msb->system = MEMSTICK_SYS_PAR8;
			host->set_param(host, MEMSTICK_INTERFACE,
					MEMSTICK_PAR8);
			printk(KERN_INFO
			       "%s: switching to 8-bit parallel mode\n",
			       card->dev.bus_id);
		} else
			printk(KERN_WARNING
			       "%s: could not switch to 8-bit mode, error %d\n",
			       card->dev.bus_id, rc);
	}


	card->next_request = h_mspro_block_req_init;
	card->next_request = h_mspro_block_req_init;
	msb->mrq_handler = h_mspro_block_default;
	msb->mrq_handler = h_mspro_block_default;
	memstick_init_req(&card->current_mrq, MS_TPC_GET_INT, NULL, 1);
	memstick_init_req(&card->current_mrq, MS_TPC_GET_INT, NULL, 1);
	memstick_new_req(card->host);
	memstick_new_req(card->host);
	wait_for_completion(&card->mrq_complete);
	wait_for_completion(&card->mrq_complete);
	rc = card->current_mrq.error;


	if (card->current_mrq.error) {
	if (rc) {
		printk(KERN_WARNING
		       "%s: interface error, trying to fall back to serial\n",
		       card->dev.bus_id);
		msb->system = MEMSTICK_SYS_SERIAL;
		msb->system = MEMSTICK_SYS_SERIAL;
		host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF);
		host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF);
		msleep(1000);
		msleep(10);
		host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON);
		host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON);
		host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL);
		host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL);


		if (memstick_set_rw_addr(card))
		rc = memstick_set_rw_addr(card);
			return card->current_mrq.error;
		if (!rc)

			rc = mspro_block_set_interface(card, msb->system);
		param.system = msb->system;

		card->next_request = h_mspro_block_req_init;
		msb->mrq_handler = h_mspro_block_default;
		memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, &param,
				  sizeof(param));
		memstick_new_req(host);
		wait_for_completion(&card->mrq_complete);

		return -EFAULT;
	}
	}

	return rc;
	return 0;
}
}


/* Memory allocated for attributes by this function should be freed by
/* Memory allocated for attributes by this function should be freed by
@@ -1053,12 +1083,11 @@ static int mspro_block_init_card(struct memstick_dev *card)
		return -EIO;
		return -EIO;


	msb->caps = host->caps;
	msb->caps = host->caps;
	if (msb->caps & MEMSTICK_CAP_PAR4) {
	rc = mspro_block_switch_interface(card);
		if (mspro_block_switch_to_parallel(card))
	if (rc)
			printk(KERN_WARNING "%s: could not switch to "
		return rc;
			       "parallel interface\n", card->dev.bus_id);
	}


	msleep(200);
	rc = mspro_block_wait_for_ced(card);
	rc = mspro_block_wait_for_ced(card);
	if (rc)
	if (rc)
		return rc;
		return rc;