[PATCH] mmc: wbsd Secure Digital support
Add support for Secure Digital specific features in the wbsd driver. Adds support for read-only switch and wide bus transfers. Signed-off-by: Pierre Ossman <drzeus@drzeus.cx> Cc: Russell King <rmk@arm.linux.org.uk> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
e619524fe5
commit
65ae2118e8
2 changed files with 57 additions and 6 deletions
|
@ -720,11 +720,28 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
|
||||||
* calculate CRC.
|
* calculate CRC.
|
||||||
*
|
*
|
||||||
* Space for CRC must be included in the size.
|
* Space for CRC must be included in the size.
|
||||||
|
* Two bytes are needed for each data line.
|
||||||
*/
|
*/
|
||||||
blksize = (1 << data->blksz_bits) + 2;
|
if (host->bus_width == MMC_BUS_WIDTH_1)
|
||||||
|
{
|
||||||
|
blksize = (1 << data->blksz_bits) + 2;
|
||||||
|
|
||||||
|
wbsd_write_index(host, WBSD_IDX_PBSMSB, (blksize >> 4) & 0xF0);
|
||||||
|
wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
|
||||||
|
}
|
||||||
|
else if (host->bus_width == MMC_BUS_WIDTH_4)
|
||||||
|
{
|
||||||
|
blksize = (1 << data->blksz_bits) + 2 * 4;
|
||||||
|
|
||||||
wbsd_write_index(host, WBSD_IDX_PBSMSB, (blksize >> 4) & 0xF0);
|
wbsd_write_index(host, WBSD_IDX_PBSMSB, ((blksize >> 4) & 0xF0)
|
||||||
wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
|
| WBSD_DATA_WIDTH);
|
||||||
|
wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data->error = MMC_ERR_INVALID;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clear the FIFO. This is needed even for DMA
|
* Clear the FIFO. This is needed even for DMA
|
||||||
|
@ -960,9 +977,9 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
|
||||||
struct wbsd_host* host = mmc_priv(mmc);
|
struct wbsd_host* host = mmc_priv(mmc);
|
||||||
u8 clk, setup, pwr;
|
u8 clk, setup, pwr;
|
||||||
|
|
||||||
DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u\n",
|
DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
|
||||||
ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select,
|
ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select,
|
||||||
ios->vdd);
|
ios->vdd, ios->bus_width);
|
||||||
|
|
||||||
spin_lock_bh(&host->lock);
|
spin_lock_bh(&host->lock);
|
||||||
|
|
||||||
|
@ -1010,6 +1027,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
|
||||||
setup = wbsd_read_index(host, WBSD_IDX_SETUP);
|
setup = wbsd_read_index(host, WBSD_IDX_SETUP);
|
||||||
if (ios->chip_select == MMC_CS_HIGH)
|
if (ios->chip_select == MMC_CS_HIGH)
|
||||||
{
|
{
|
||||||
|
BUG_ON(ios->bus_width != MMC_BUS_WIDTH_1);
|
||||||
setup |= WBSD_DAT3_H;
|
setup |= WBSD_DAT3_H;
|
||||||
host->flags |= WBSD_FIGNORE_DETECT;
|
host->flags |= WBSD_FIGNORE_DETECT;
|
||||||
}
|
}
|
||||||
|
@ -1025,12 +1043,41 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
|
||||||
}
|
}
|
||||||
wbsd_write_index(host, WBSD_IDX_SETUP, setup);
|
wbsd_write_index(host, WBSD_IDX_SETUP, setup);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Store bus width for later. Will be used when
|
||||||
|
* setting up the data transfer.
|
||||||
|
*/
|
||||||
|
host->bus_width = ios->bus_width;
|
||||||
|
|
||||||
spin_unlock_bh(&host->lock);
|
spin_unlock_bh(&host->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int wbsd_get_ro(struct mmc_host* mmc)
|
||||||
|
{
|
||||||
|
struct wbsd_host* host = mmc_priv(mmc);
|
||||||
|
u8 csr;
|
||||||
|
|
||||||
|
spin_lock_bh(&host->lock);
|
||||||
|
|
||||||
|
csr = inb(host->base + WBSD_CSR);
|
||||||
|
csr |= WBSD_MSLED;
|
||||||
|
outb(csr, host->base + WBSD_CSR);
|
||||||
|
|
||||||
|
mdelay(1);
|
||||||
|
|
||||||
|
csr = inb(host->base + WBSD_CSR);
|
||||||
|
csr &= ~WBSD_MSLED;
|
||||||
|
outb(csr, host->base + WBSD_CSR);
|
||||||
|
|
||||||
|
spin_unlock_bh(&host->lock);
|
||||||
|
|
||||||
|
return csr & WBSD_WRPT;
|
||||||
|
}
|
||||||
|
|
||||||
static struct mmc_host_ops wbsd_ops = {
|
static struct mmc_host_ops wbsd_ops = {
|
||||||
.request = wbsd_request,
|
.request = wbsd_request,
|
||||||
.set_ios = wbsd_set_ios,
|
.set_ios = wbsd_set_ios,
|
||||||
|
.get_ro = wbsd_get_ro,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*****************************************************************************\
|
/*****************************************************************************\
|
||||||
|
@ -1355,6 +1402,7 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
|
||||||
mmc->f_min = 375000;
|
mmc->f_min = 375000;
|
||||||
mmc->f_max = 24000000;
|
mmc->f_max = 24000000;
|
||||||
mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
|
mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
|
||||||
|
mmc->caps = MMC_CAP_4_BIT_DATA;
|
||||||
|
|
||||||
spin_lock_init(&host->lock);
|
spin_lock_init(&host->lock);
|
||||||
|
|
||||||
|
|
|
@ -106,6 +106,8 @@
|
||||||
#define WBSD_CLK_16M 0x02
|
#define WBSD_CLK_16M 0x02
|
||||||
#define WBSD_CLK_24M 0x03
|
#define WBSD_CLK_24M 0x03
|
||||||
|
|
||||||
|
#define WBSD_DATA_WIDTH 0x01
|
||||||
|
|
||||||
#define WBSD_DAT3_H 0x08
|
#define WBSD_DAT3_H 0x08
|
||||||
#define WBSD_FIFO_RESET 0x04
|
#define WBSD_FIFO_RESET 0x04
|
||||||
#define WBSD_SOFT_RESET 0x02
|
#define WBSD_SOFT_RESET 0x02
|
||||||
|
@ -164,6 +166,7 @@ struct wbsd_host
|
||||||
int firsterr; /* See fifo functions */
|
int firsterr; /* See fifo functions */
|
||||||
|
|
||||||
u8 clk; /* Current clock speed */
|
u8 clk; /* Current clock speed */
|
||||||
|
unsigned char bus_width; /* Current bus width */
|
||||||
|
|
||||||
int config; /* Config port */
|
int config; /* Config port */
|
||||||
u8 unlock_code; /* Code to unlock config */
|
u8 unlock_code; /* Code to unlock config */
|
||||||
|
|
Loading…
Add table
Reference in a new issue