Implemented more SD Card commands.

This commit is contained in:
claudiol 2018-09-28 17:57:37 -04:00
parent 9118d40ca4
commit dcdcf7756e

View file

@ -54,6 +54,8 @@ typedef struct {
unsigned int write_index; unsigned int write_index;
int multiple_block; int multiple_block;
int acmd;
int card_state;
} s3c2410_sdi_t; } s3c2410_sdi_t;
@ -227,17 +229,18 @@ s3c2410_sdi_read(void *opaque, target_phys_addr_t offset)
switch (offset) { switch (offset) {
case S3C2410_SDI_SDIDAT: case S3C2410_SDI_SDIDAT:
if( (sdi->sdidcon&0x3000)==0x2000) {
read_avail = sdi->nr_read_data - sdi->read_index; read_avail = sdi->nr_read_data - sdi->read_index;
if (read_avail > 0) { if (read_avail > 0) {
*(reg->datap) = sdi->read_data[sdi->read_index++] << 24; *(reg->datap) = sdi->read_data[sdi->read_index++] << 0;
if ((sdi->nr_read_data - sdi->read_index) > 0) { if ((sdi->nr_read_data - sdi->read_index) > 0) {
*(reg->datap) |= sdi->read_data[sdi->read_index++] << 16; *(reg->datap) |= sdi->read_data[sdi->read_index++] << 8;
} }
if ((sdi->nr_read_data - sdi->read_index) > 0) { if ((sdi->nr_read_data - sdi->read_index) > 0) {
*(reg->datap) |= sdi->read_data[sdi->read_index++] << 8; *(reg->datap) |= sdi->read_data[sdi->read_index++] << 16;
} }
if ((sdi->nr_read_data - sdi->read_index) > 0) { if ((sdi->nr_read_data - sdi->read_index) > 0) {
*(reg->datap) |= sdi->read_data[sdi->read_index++] << 0; *(reg->datap) |= sdi->read_data[sdi->read_index++] << 24;
} }
if (sdi->read_index >= sdi->nr_read_data) { if (sdi->read_index >= sdi->nr_read_data) {
@ -253,12 +256,15 @@ s3c2410_sdi_read(void *opaque, target_phys_addr_t offset)
sdi->sdidsta |= (1 << 9) | (1 << 4); sdi->sdidsta |= (1 << 9) | (1 << 4);
} else { } else {
sdi->nr_read_data = 0; sdi->nr_read_data = 0;
sdi->sdidcon&=~0x3000;
} }
} }
read_avail = sdi->nr_read_data - sdi->read_index; read_avail = sdi->nr_read_data - sdi->read_index;
sdi->sdidcnt = read_avail; sdi->sdidcnt = read_avail;
}
else *(reg->datap)=0;
} }
break; break;
@ -275,15 +281,18 @@ s3c2410_sdi_read(void *opaque, target_phys_addr_t offset)
break; break;
case S3C2410_SDI_SDIDSTA: case S3C2410_SDI_SDIDSTA:
*(reg->datap) &= ~(0x0f); *(reg->datap) &= ~(0x03);
if( (sdi->sdidcon&0x3000)==0x1000) {
*(reg->datap) |= (1 << 3);
sdi->sdidcon&=~0x3000; // BACK TO READY STATE
}
read_avail = sdi->nr_read_data - sdi->read_index; read_avail = sdi->nr_read_data - sdi->read_index;
if (read_avail) { if ( ((sdi->sdidcon&0x3000)==0x2000) && read_avail) {
*(reg->datap) |= (1 << 0); *(reg->datap) |= (1 << 0);
} }
write_avail = sdi->nr_write_data - sdi->write_index; write_avail = sdi->nr_write_data - sdi->write_index;
if (write_avail) { if ( ((sdi->sdidcon&0x3000)==0x3000) && write_avail) {
*(reg->datap) |= (1 << 1); *(reg->datap) |= (1 << 1);
} }
} }
@ -349,8 +358,11 @@ s3c2410_sdi_write(void *opaque, target_phys_addr_t offset, uint32_t data)
if (data & (1 << 9)) { if (data & (1 << 9)) {
sdi->sdicsta |= (1 << 9); sdi->sdicsta |= (1 << 9);
switch (data & 0x3f) { switch ((data & 0x3f)+(sdi->acmd<<8)) {
case 256:
case 0: case 0:
sdi->acmd=0;
sdi->card_state=0;
break; break;
case 1: case 1:
@ -360,6 +372,7 @@ s3c2410_sdi_write(void *opaque, target_phys_addr_t offset, uint32_t data)
break; break;
case 2: case 2:
sdi->card_state=2;
sdi->sdicsta |= 0x3f; sdi->sdicsta |= 0x3f;
sdi->sdirsp0 = 0x02000053; sdi->sdirsp0 = 0x02000053;
sdi->sdirsp1 = 0x444d3036; sdi->sdirsp1 = 0x444d3036;
@ -368,8 +381,12 @@ s3c2410_sdi_write(void *opaque, target_phys_addr_t offset, uint32_t data)
break; break;
case 3: case 3:
sdi->card_state=3;
sdi->sdicsta |= 3; sdi->sdicsta |= 3;
sdi->sdirsp0 = 0x00000700; sdi->sdirsp0 = sdi->card_state<<9;
if(sdi->card_state==5) sdi->sdirsp0 |=0x100;
if(sdi->acmd) sdi->sdirsp0|=0x20;
sdi->sdirsp0|=0x12340000; // PUBLISHED RCA NUMBER
sdi->sdirsp1 = 0xff000000; sdi->sdirsp1 = 0xff000000;
break; break;
@ -378,6 +395,9 @@ s3c2410_sdi_write(void *opaque, target_phys_addr_t offset, uint32_t data)
sdi->sdirsp0 = 0x00000900; sdi->sdirsp0 = 0x00000900;
sdi->sdirsp1 = 0xff000000; sdi->sdirsp1 = 0xff000000;
break; break;
case 8:
sdi->sdicsta |=0x400; // SEND TIMEOUT IMMEDIATELY
break;
case 9: case 9:
{ {
@ -418,6 +438,14 @@ s3c2410_sdi_write(void *opaque, target_phys_addr_t offset, uint32_t data)
sdi->sdirsp0 = 0x00000900; sdi->sdirsp0 = 0x00000900;
sdi->sdirsp1 = 0xff000000; sdi->sdirsp1 = 0xff000000;
break; break;
case 16:
sdi->sdicsta |= 16;
sdi->sdicsta |= data & 0x3f;
sdi->sdirsp0 = sdi->card_state<<9;
if(sdi->card_state==5) sdi->sdirsp0 |=0x100;
if(sdi->acmd) sdi->sdirsp0|=0x20;
sdi->sdirsp1 = 0xff000000;
break;
case 18: case 18:
sdi->multiple_block = 1; sdi->multiple_block = 1;
@ -453,12 +481,49 @@ s3c2410_sdi_write(void *opaque, target_phys_addr_t offset, uint32_t data)
sdi->sdirsp1 = 0xff000000; sdi->sdirsp1 = 0xff000000;
sdi->sdidcnt = (1 << 12) | write_avail; sdi->sdidcnt = (1 << 12) | write_avail;
break; break;
case 256+55:
case 55:
sdi->acmd=1;
sdi->sdicsta |= data & 0x3f;
sdi->sdirsp0 = sdi->card_state<<9;
if(sdi->card_state==5) sdi->sdirsp0 |=0x100;
if(sdi->acmd) sdi->sdirsp0|=0x20;
sdi->sdirsp1 = 0xff000000;
break;
case 256+41:
// ACMD41
sdi->card_state= 1; // READY
sdi->sdicsta |= data & 0x3f;
sdi->sdirsp0 = 0x80ff8000;
sdi->sdirsp1 = 0xff000000;
sdi->acmd=0;
break;
case 256+42:
// ACMD42
sdi->sdicsta |= data & 0x3f;
sdi->sdirsp0 = sdi->card_state<<9;
if(sdi->card_state==5) sdi->sdirsp0 |=0x100;
if(sdi->acmd) sdi->sdirsp0|=0x20;
sdi->sdirsp1 = 0xff000000;
break;
case 256+51:
// ACMD51
sdi->sdicsta |= 51;
sdi->sdirsp0 = 0x0;
sdi->sdirsp1 = 0x01050000;
sdi->sdirsp2 = 0x0;
sdi->sdirsp3 = 0x0;
sdi->acmd=0;
break;
default: default:
printf("unhandled SDcard CMD %u\n", (data & 0x3f)); printf("unhandled SDcard CMD %u\n", (data & 0x3f));
sdi->sdicsta |= (1 << 10); sdi->sdicsta |= (1 << 10);
sdi->sdicsta &= ~(1 << 9); sdi->sdicsta &= ~(1 << 9);
sdi->acmd=0;
// abort(); // abort();
break; break;
@ -469,18 +534,18 @@ s3c2410_sdi_write(void *opaque, target_phys_addr_t offset, uint32_t data)
case S3C2410_SDI_SDIDAT: case S3C2410_SDI_SDIDAT:
*(reg->datap) = data; *(reg->datap) = data;
if((sdi->sdidcon&0x3000)==0x3000) {
write_avail = sdi->nr_write_data - sdi->write_index; write_avail = sdi->nr_write_data - sdi->write_index;
if (write_avail > 0) { if (write_avail > 0) {
sdi->write_data[sdi->write_index++] = (*(reg->datap) >> 24) & 0xff; sdi->write_data[sdi->write_index++] = (*(reg->datap) >> 0) & 0xff;
if ((sdi->nr_write_data - sdi->write_index) > 0) { if ((sdi->nr_write_data - sdi->write_index) > 0) {
sdi->write_data[sdi->write_index++] = (*(reg->datap) >> 16) & 0xff; sdi->write_data[sdi->write_index++] = (*(reg->datap) >> 8) & 0xff;
} }
if ((sdi->nr_write_data - sdi->write_index) > 0) { if ((sdi->nr_write_data - sdi->write_index) > 0) {
sdi->write_data[sdi->write_index++] = (*(reg->datap) >> 8) & 0xff; sdi->write_data[sdi->write_index++] = (*(reg->datap) >> 16) & 0xff;
} }
if ((sdi->nr_write_data - sdi->write_index) > 0) { if ((sdi->nr_write_data - sdi->write_index) > 0) {
sdi->write_data[sdi->write_index++] = (*(reg->datap) >> 0) & 0xff; sdi->write_data[sdi->write_index++] = (*(reg->datap) >> 24) & 0xff;
} }
if (sdi->write_index >= sdi->nr_write_data) { if (sdi->write_index >= sdi->nr_write_data) {
@ -491,14 +556,17 @@ s3c2410_sdi_write(void *opaque, target_phys_addr_t offset, uint32_t data)
sdcard_write_prepare(sdi); sdcard_write_prepare(sdi);
} else { } else {
sdi->nr_write_data = 0; sdi->nr_write_data = 0;
sdi->sdidcon&=~0x3000;
} }
sdi->sdidsta |= (1 << 9) | (1 << 4); sdi->sdidsta |= (1 << 9) | (1 << 4) | (1<<3);
} }
write_avail = sdi->nr_write_data - sdi->write_index; write_avail = sdi->nr_write_data - sdi->write_index;
sdi->sdidcnt = write_avail; sdi->sdidcnt = write_avail;
}
} }
break; break;
@ -507,7 +575,7 @@ s3c2410_sdi_write(void *opaque, target_phys_addr_t offset, uint32_t data)
break; break;
case S3C2410_SDI_SDIDSTA: case S3C2410_SDI_SDIDSTA:
*(reg->datap) &= ~(data & 0x3f8); *(reg->datap) &= ~(data & 0x7fc);
break; break;
case S3C2410_SDI_SDIFSTA: case S3C2410_SDI_SDIFSTA: