Commit ea55a221 authored by Philippe Mathieu-Daudé's avatar Philippe Mathieu-Daudé Committed by Paolo Bonzini
Browse files

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: default avatarPhilippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: default avatarAlistair Francis <alistair.francis@xilinx.com>
Message-Id: <20180208164818.7961-20-f4bug@amsat.org>
parent 06c5120b
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -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);
+19 −3
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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 */