--- b/ar6000/hif/hif2.c	2009-03-30 00:28:33.000000000 +0400
+++ c/ar6000//hif/hif2.c	2009-03-30 00:33:59.000000000 +0400
@@ -25,6 +25,8 @@
 #include <linux/sched.h>
 #include <linux/mmc/sdio_func.h>
 #include <linux/mmc/sdio.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
 
 /*
  * turn on GTA02 platform depened code.
@@ -42,6 +44,8 @@
 #include "a_types.h"
 #include "hif.h"
 
+extern A_UINT32 onebitmode;
+
 /*
  * KNOWN BUGS:
  *
@@ -473,6 +477,56 @@
 }
 
 
+/*
+ * sdio_f0_writeb function allow write only to address range 0xF0...0xFF.
+ * this function is a copy of 'mmc_io_rw_direct' (mmc/core/sdio_ops.c)
+ * for leave out this restriction.
+ */
+static int sdio_rw_direct(struct mmc_card *card, int write, unsigned fn,
+	unsigned addr, u8 in, u8* out)
+{
+	struct mmc_command cmd;
+	int err;
+
+	BUG_ON(!card);
+	BUG_ON(fn > 7);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = SD_IO_RW_DIRECT;
+	cmd.arg = write ? 0x80000000 : 0x00000000;
+	cmd.arg |= fn << 28;
+	cmd.arg |= (write && out) ? 0x08000000 : 0x00000000;
+	cmd.arg |= addr << 9;
+	cmd.arg |= in;
+	cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC;
+
+	err = mmc_wait_for_cmd(card->host, &cmd, 0);
+	if (err)
+		return err;
+
+	if (mmc_host_is_spi(card->host)) {
+		/* host driver already reported errors */
+	} else {
+		if (cmd.resp[0] & R5_ERROR)
+			return -EIO;
+		if (cmd.resp[0] & R5_FUNCTION_NUMBER)
+			return -EINVAL;
+		if (cmd.resp[0] & R5_OUT_OF_RANGE)
+			return -ERANGE;
+	}
+
+	if (out) {
+		if (mmc_host_is_spi(card->host))
+			*out = (cmd.resp[0] >> 8) & 0xFF;
+		else
+			*out = cmd.resp[0] & 0xFF;
+	}
+
+	return 0;
+}
+
+
 /* ----- Device probe and removal (Linux side) ----------------------------- */
 
 
@@ -485,6 +539,40 @@
 	dev_dbg(dev, "ar6000_do_activate\n");
 
 	sdio_claim_host(func);
+
+	if (onebitmode)
+	{
+		struct mmc_card *card;
+		struct mmc_host *host;
+		u8 ctrl;
+
+		/*
+		 * Init SDIO 1-wire mode.
+		 */
+		card = func->card;
+		host = card->host;
+
+		ret = sdio_rw_direct (card, 0, 0, SDIO_CCCR_IF, 0, &ctrl);
+		if (ret) {
+			dev_err(dev, "sdio_f0_readb (SDIO_CCCR_IF) returns %d\n",
+			        ret);
+			goto out_claimed;
+		}
+
+		ctrl &= ~(SDIO_BUS_WIDTH_4BIT|SDIO_BUS_WIDTH_1BIT);
+		ctrl |= SDIO_BUS_WIDTH_1BIT;
+
+		ret = sdio_rw_direct (card, 1, 0, SDIO_CCCR_IF, ctrl, NULL);
+		if (ret) {
+			dev_err(dev, "sdio_f0_writeb (SDIO_CCCR_IF) returns %d\n",
+			        ret);
+			goto out_claimed;
+		}
+
+		host->ios.bus_width = MMC_BUS_WIDTH_1;
+		host->ops->set_ios(host, &host->ios);
+	}
+
 	sdio_enable_func(func);
 
 	INIT_LIST_HEAD(&hif->queue);
@@ -540,6 +628,8 @@
 
 out_enabled:
 	sdio_disable_func(func);
+
+out_claimed:
 	sdio_release_host(func);
 
 	return ret;
@@ -577,6 +667,40 @@
 	sdio_claim_host(func);
 	sdio_release_irq(func);
 	sdio_disable_func(func);
+
+	if (onebitmode)
+	{
+		struct mmc_card *card;
+		struct mmc_host *host;
+		u8 ctrl;
+
+		/*
+		 * Release SDIO 1-wire mode,
+		 * or init back to SDIO 4-wire.
+		 */
+		card = func->card;
+		host = card->host;
+
+		ret = sdio_rw_direct (card, 0, 0, SDIO_CCCR_IF, 0, &ctrl);
+		if (ret) {
+			dev_err(dev, "sdio_f0_readb (SDIO_CCCR_IF) returns %d\n",
+			        ret);
+			ctrl = 0;
+		}
+
+		ctrl &= ~(SDIO_BUS_WIDTH_4BIT|SDIO_BUS_WIDTH_1BIT);
+		ctrl |= SDIO_BUS_WIDTH_4BIT;
+
+		ret = sdio_rw_direct (card, 1, 0, SDIO_CCCR_IF, ctrl, NULL);
+		if (ret) {
+			dev_err(dev, "sdio_f0_writeb (SDIO_CCCR_IF) returns %d\n",
+			        ret);
+		}
+
+		host->ios.bus_width = MMC_BUS_WIDTH_1;
+		host->ops->set_ios(host, &host->ios);
+	}
+
 	sdio_release_host(func);
 }
 
