sdhci: implement the Host Control 2 register (tuning sequence)
[based on a patch from Alistair Francis <alistair.francis@xilinx.com> from qemu/xilinx tag xilinx-v2015.2] Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Reviewed-by: Alistair Francis <alistair.francis@xilinx.com> Message-Id: <20180208164818.7961-20-f4bug@amsat.org>
This commit is contained in:
parent
06c5120b09
commit
ea55a221bf
@ -188,6 +188,16 @@ FIELD(SDHC_ACMD12ERRSTS, TIMEOUT_ERR, 1, 1);
|
||||
FIELD(SDHC_ACMD12ERRSTS, CRC_ERR, 2, 1);
|
||||
FIELD(SDHC_ACMD12ERRSTS, INDEX_ERR, 4, 1);
|
||||
|
||||
/* Host Control Register 2 (since v3) */
|
||||
#define SDHC_HOSTCTL2 0x3E
|
||||
FIELD(SDHC_HOSTCTL2, UHS_MODE_SEL, 0, 3);
|
||||
FIELD(SDHC_HOSTCTL2, V18_ENA, 3, 1); /* UHS-I only */
|
||||
FIELD(SDHC_HOSTCTL2, DRIVER_STRENGTH, 4, 2); /* UHS-I only */
|
||||
FIELD(SDHC_HOSTCTL2, EXECUTE_TUNING, 6, 1); /* UHS-I only */
|
||||
FIELD(SDHC_HOSTCTL2, SAMPLING_CLKSEL, 7, 1); /* UHS-I only */
|
||||
FIELD(SDHC_HOSTCTL2, ASYNC_INT, 14, 1);
|
||||
FIELD(SDHC_HOSTCTL2, PRESET_ENA, 15, 1);
|
||||
|
||||
/* HWInit Capabilities Register 0x05E80080 */
|
||||
#define SDHC_CAPAB 0x40
|
||||
FIELD(SDHC_CAPAB, TOCLKFREQ, 0, 6);
|
||||
|
@ -408,14 +408,29 @@ static void sdhci_end_transfer(SDHCIState *s)
|
||||
static void sdhci_read_block_from_card(SDHCIState *s)
|
||||
{
|
||||
int index = 0;
|
||||
uint8_t data;
|
||||
const uint16_t blk_size = s->blksize & BLOCK_SIZE_MASK;
|
||||
|
||||
if ((s->trnmod & SDHC_TRNS_MULTI) &&
|
||||
(s->trnmod & SDHC_TRNS_BLK_CNT_EN) && (s->blkcnt == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (index = 0; index < (s->blksize & BLOCK_SIZE_MASK); index++) {
|
||||
s->fifo_buffer[index] = sdbus_read_data(&s->sdbus);
|
||||
for (index = 0; index < blk_size; index++) {
|
||||
data = sdbus_read_data(&s->sdbus);
|
||||
if (!FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, EXECUTE_TUNING)) {
|
||||
/* Device is not in tunning */
|
||||
s->fifo_buffer[index] = data;
|
||||
}
|
||||
}
|
||||
|
||||
if (FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, EXECUTE_TUNING)) {
|
||||
/* Device is in tunning */
|
||||
s->hostctl2 &= ~R_SDHC_HOSTCTL2_EXECUTE_TUNING_MASK;
|
||||
s->hostctl2 |= R_SDHC_HOSTCTL2_SAMPLING_CLKSEL_MASK;
|
||||
s->prnsts &= ~(SDHC_DAT_LINE_ACTIVE | SDHC_DOING_READ |
|
||||
SDHC_DATA_INHIBIT);
|
||||
goto read_done;
|
||||
}
|
||||
|
||||
/* New data now available for READ through Buffer Port Register */
|
||||
@ -440,6 +455,7 @@ static void sdhci_read_block_from_card(SDHCIState *s)
|
||||
}
|
||||
}
|
||||
|
||||
read_done:
|
||||
sdhci_update_irq(s);
|
||||
}
|
||||
|
||||
@ -1005,7 +1021,7 @@ static uint64_t sdhci_read(void *opaque, hwaddr offset, unsigned size)
|
||||
ret = s->norintsigen | (s->errintsigen << 16);
|
||||
break;
|
||||
case SDHC_ACMD12ERRSTS:
|
||||
ret = s->acmd12errsts;
|
||||
ret = s->acmd12errsts | (s->hostctl2 << 16);
|
||||
break;
|
||||
case SDHC_CAPAB:
|
||||
ret = (uint32_t)s->capareg;
|
||||
|
@ -73,6 +73,7 @@ typedef struct SDHCIState {
|
||||
uint16_t norintsigen; /* Normal Interrupt Signal Enable Register */
|
||||
uint16_t errintsigen; /* Error Interrupt Signal Enable Register */
|
||||
uint16_t acmd12errsts; /* Auto CMD12 error status register */
|
||||
uint16_t hostctl2; /* Host Control 2 */
|
||||
uint64_t admasysaddr; /* ADMA System Address Register */
|
||||
|
||||
/* Read-only registers */
|
||||
|
Loading…
Reference in New Issue
Block a user