Skip to content

Commit

Permalink
sdio: read and decode interesting parts of the CCCR
Browse files Browse the repository at this point in the history
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
  • Loading branch information
Pierre Ossman committed Sep 23, 2007
1 parent fa64efa commit 35c66c1
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 0 deletions.
63 changes: 63 additions & 0 deletions drivers/mmc/core/sdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include <linux/mmc/host.h>
#include <linux/mmc/card.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/sdio_func.h>

#include "core.h"
Expand All @@ -39,6 +40,61 @@ static int sdio_init_func(struct mmc_card *card, unsigned int fn)
return 0;
}

static int sdio_read_cccr(struct mmc_card *card)
{
int ret;
int cccr_vsn;
unsigned char data;

memset(&card->cccr, 0, sizeof(struct sdio_cccr));

ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_CCCR, 0, &data);
if (ret)
goto out;

cccr_vsn = data & 0x0f;

if (cccr_vsn > SDIO_CCCR_REV_1_20) {
printk(KERN_ERR "%s: unrecognised CCCR structure version %d\n",
mmc_hostname(card->host), cccr_vsn);
return -EINVAL;
}

card->cccr.sdio_vsn = (data & 0xf0) >> 4;

ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_CAPS, 0, &data);
if (ret)
goto out;

if (data & SDIO_CCCR_CAP_SMB)
card->cccr.multi_block = 1;
if (data & SDIO_CCCR_CAP_LSC)
card->cccr.low_speed = 1;
if (data & SDIO_CCCR_CAP_4BLS)
card->cccr.wide_bus = 1;

if (cccr_vsn >= SDIO_CCCR_REV_1_10) {
ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_POWER, 0, &data);
if (ret)
goto out;

if (data & SDIO_POWER_SMPC)
card->cccr.high_power = 1;
}

if (cccr_vsn >= SDIO_CCCR_REV_1_20) {
ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &data);
if (ret)
goto out;

if (data & SDIO_SPEED_SHS)
card->cccr.high_speed = 1;
}

out:
return ret;
}

/*
* Host is being removed. Free up the current card.
*/
Expand Down Expand Up @@ -180,6 +236,13 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
if (err)
goto remove;

/*
* Read the common registers.
*/
err = sdio_read_cccr(card);
if (err)
goto remove;

/*
* Initialize (but don't add) all present functions.
*/
Expand Down
11 changes: 11 additions & 0 deletions include/linux/mmc/card.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ struct sd_switch_caps {
unsigned int hs_max_dtr;
};

struct sdio_cccr {
unsigned int sdio_vsn;
unsigned int sd_vsn;
unsigned int multi_block:1,
low_speed:1,
wide_bus:1,
high_power:1,
high_speed:1;
};

struct mmc_host;
struct sdio_func;

Expand Down Expand Up @@ -87,6 +97,7 @@ struct mmc_card {
struct sd_switch_caps sw_caps; /* switch (CMD6) caps */

unsigned int sdio_funcs; /* number of SDIO functions */
struct sdio_cccr cccr; /* common card info */
struct sdio_func *sdio_func[SDIO_MAX_FUNCS]; /* SDIO functions (devices) */
};

Expand Down

0 comments on commit 35c66c1

Please sign in to comment.