mirror of
https://github.com/gwenhael-le-moine/x49gp.git
synced 2024-12-25 21:58:49 +01:00
Implemented more SD Card commands.
This commit is contained in:
parent
9118d40ca4
commit
dcdcf7756e
1 changed files with 85 additions and 17 deletions
102
s3c2410_sdi.c
102
s3c2410_sdi.c
|
@ -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:
|
||||||
|
|
Loading…
Reference in a new issue