aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorbalrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162>2007-12-24 14:41:39 +0000
committerbalrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162>2007-12-24 14:41:39 +0000
commit1b0889958e875df85c7b2353498ed2cac16415ce (patch)
tree9aef8f74030a981f213cf333614d62d9a9c1b4d6 /hw
parenta1daafd8df0d8acfce48ba220337ef7f895cfd85 (diff)
Implement SD CMD8 and R7 from the newer SD Physical Spec Version 2.00.
Remove bogus setting of bits 63 of R2 type responses. Make some constants static to allow definitions by the same name for SDIO. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3850 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'hw')
-rw-r--r--hw/sd.c43
1 files changed, 38 insertions, 5 deletions
diff --git a/hw/sd.c b/hw/sd.c
index e6e80db0ea..1f71d85a52 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -49,6 +49,7 @@ typedef enum {
sd_r2_s, /* CSD register */
sd_r3, /* OCR register */
sd_r6 = 6, /* Published RCA response */
+ sd_r7, /* Operating voltage */
sd_r1b = -1,
} sd_rsp_type_t;
@@ -77,6 +78,7 @@ struct SDState {
uint16_t rca;
uint32_t card_status;
uint8_t sd_status[64];
+ uint32_t vhs;
int wp_switch;
int *wp_groups;
uint32_t size;
@@ -126,9 +128,9 @@ static void sd_set_status(SDState *sd)
sd->card_status |= sd->state << 9;
}
-const sd_cmd_type_t sd_cmd_type[64] = {
+static const sd_cmd_type_t sd_cmd_type[64] = {
sd_bc, sd_none, sd_bcr, sd_bcr, sd_none, sd_none, sd_none, sd_ac,
- sd_none, sd_ac, sd_ac, sd_adtc, sd_ac, sd_ac, sd_none, sd_ac,
+ sd_bcr, sd_ac, sd_ac, sd_adtc, sd_ac, sd_ac, sd_none, sd_ac,
sd_ac, sd_adtc, sd_adtc, sd_none, sd_none, sd_none, sd_none, sd_none,
sd_adtc, sd_adtc, sd_adtc, sd_adtc, sd_ac, sd_ac, sd_adtc, sd_none,
sd_ac, sd_ac, sd_none, sd_none, sd_none, sd_none, sd_ac, sd_none,
@@ -137,7 +139,7 @@ const sd_cmd_type_t sd_cmd_type[64] = {
sd_adtc, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none,
};
-const sd_cmd_type_t sd_acmd_type[64] = {
+static const sd_cmd_type_t sd_acmd_type[64] = {
sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_ac, sd_none,
sd_none, sd_none, sd_none, sd_none, sd_none, sd_adtc, sd_none, sd_none,
sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_adtc, sd_ac,
@@ -190,6 +192,7 @@ static uint16_t sd_crc16(void *message, size_t width)
static void sd_set_ocr(SDState *sd)
{
+ /* All voltages OK, card power-up OK, Standard Capacity SD Memory Card */
sd->ocr = 0x80ffff80;
}
@@ -349,6 +352,14 @@ static void sd_response_r6_make(SDState *sd, uint8_t *response)
response[3] = status & 0xff;
}
+static void sd_response_r7_make(SDState *sd, uint8_t *response)
+{
+ response[0] = (sd->vhs >> 24) & 0xff;
+ response[1] = (sd->vhs >> 16) & 0xff;
+ response[2] = (sd->vhs >> 8) & 0xff;
+ response[3] = (sd->vhs >> 0) & 0xff;
+}
+
static void sd_reset(SDState *sd, BlockDriverState *bdrv)
{
uint32_t size;
@@ -685,6 +696,25 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
}
break;
+ case 8: /* CMD8: SEND_IF_COND */
+ /* Physical Layer Specification Version 2.00 command */
+ switch (sd->state) {
+ case sd_idle_state:
+ sd->vhs = 0;
+
+ /* No response if not exactly one VHS bit is set. */
+ if (!(req.arg >> 8) || (req.arg >> ffs(req.arg & ~0xff)))
+ return sd->spi ? sd_r7 : sd_r0;
+
+ /* Accept. */
+ sd->vhs = req.arg;
+ return sd_r7;
+
+ default:
+ break;
+ }
+ break;
+
case 9: /* CMD9: SEND_CSD */
switch (sd->state) {
case sd_standby_state:
@@ -1238,13 +1268,11 @@ int sd_do_command(SDState *sd, struct sd_request_s *req,
case sd_r2_i:
memcpy(response, sd->cid, sizeof(sd->cid));
- response[7] |= 1;
rsplen = 16;
break;
case sd_r2_s:
memcpy(response, sd->csd, sizeof(sd->csd));
- response[7] |= 1;
rsplen = 16;
break;
@@ -1258,6 +1286,11 @@ int sd_do_command(SDState *sd, struct sd_request_s *req,
rsplen = 4;
break;
+ case sd_r7:
+ sd_response_r7_make(sd, response);
+ rsplen = 4;
+ break;
+
case sd_r0:
default:
rsplen = 0;