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

sdhci: implement CMD/DAT[] fields in the Present State register



[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-23-f4bug@amsat.org>
parent 0034ebe6
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -41,6 +41,40 @@ static SDState *get_card(SDBus *sdbus)
    return SD_CARD(kid->child);
}

uint8_t sdbus_get_dat_lines(SDBus *sdbus)
{
    SDState *slave = get_card(sdbus);
    uint8_t dat_lines = 0b1111; /* 4 bit bus width */

    if (slave) {
        SDCardClass *sc = SD_CARD_GET_CLASS(slave);

        if (sc->get_dat_lines) {
            dat_lines = sc->get_dat_lines(slave);
        }
    }
    trace_sdbus_get_dat_lines(sdbus_name(sdbus), dat_lines);

    return dat_lines;
}

bool sdbus_get_cmd_line(SDBus *sdbus)
{
    SDState *slave = get_card(sdbus);
    bool cmd_line = true;

    if (slave) {
        SDCardClass *sc = SD_CARD_GET_CLASS(slave);

        if (sc->get_cmd_line) {
            cmd_line = sc->get_cmd_line(slave);
        }
    }
    trace_sdbus_get_cmd_line(sdbus_name(sdbus), cmd_line);

    return cmd_line;
}

void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts)
{
    SDState *card = get_card(sdbus);
+16 −0
Original line number Diff line number Diff line
@@ -126,8 +126,20 @@ struct SDState {
    BlockBackend *blk;

    bool enable;
    uint8_t dat_lines;
    bool cmd_line;
};

static uint8_t sd_get_dat_lines(SDState *sd)
{
    return sd->enable ? sd->dat_lines : 0;
}

static bool sd_get_cmd_line(SDState *sd)
{
    return sd->enable ? sd->cmd_line : false;
}

static void sd_set_voltage(SDState *sd, uint16_t millivolts)
{
    switch (millivolts) {
@@ -457,6 +469,8 @@ static void sd_reset(DeviceState *dev)
    sd->blk_len = 0x200;
    sd->pwd_len = 0;
    sd->expecting_acmd = false;
    sd->dat_lines = 0xf;
    sd->cmd_line = true;
    sd->multi_blk_cnt = 0;
}

@@ -1939,6 +1953,8 @@ static void sd_class_init(ObjectClass *klass, void *data)
    dc->bus_type = TYPE_SD_BUS;

    sc->set_voltage = sd_set_voltage;
    sc->get_dat_lines = sd_get_dat_lines;
    sc->get_cmd_line = sd_get_cmd_line;
    sc->do_command = sd_do_command;
    sc->write_data = sd_write_data;
    sc->read_data = sd_read_data;
+2 −0
Original line number Diff line number Diff line
@@ -82,6 +82,8 @@
#define SDHC_CARD_PRESENT              0x00010000
#define SDHC_CARD_DETECT               0x00040000
#define SDHC_WRITE_PROTECT             0x00080000
FIELD(SDHC_PRNSTS, DAT_LVL,            20, 4);
FIELD(SDHC_PRNSTS, CMD_LVL,            24, 1);
#define TRANSFERRING_DATA(x)           \
    ((x) & (SDHC_DOING_READ | SDHC_DOING_WRITE))

+4 −0
Original line number Diff line number Diff line
@@ -1003,6 +1003,10 @@ static uint64_t sdhci_read(void *opaque, hwaddr offset, unsigned size)
        break;
    case SDHC_PRNSTS:
        ret = s->prnsts;
        ret = FIELD_DP32(ret, SDHC_PRNSTS, DAT_LVL,
                         sdbus_get_dat_lines(&s->sdbus));
        ret = FIELD_DP32(ret, SDHC_PRNSTS, CMD_LVL,
                         sdbus_get_cmd_line(&s->sdbus));
        break;
    case SDHC_HOSTCTL:
        ret = s->hostctl1 | (s->pwrcon << 8) | (s->blkgap << 16) |
+2 −0
Original line number Diff line number Diff line
@@ -5,6 +5,8 @@ sdbus_command(const char *bus_name, uint8_t cmd, uint32_t arg, uint8_t crc) "@%s
sdbus_read(const char *bus_name, uint8_t value) "@%s value 0x%02x"
sdbus_write(const char *bus_name, uint8_t value) "@%s value 0x%02x"
sdbus_set_voltage(const char *bus_name, uint16_t millivolts) "@%s %u (mV)"
sdbus_get_dat_lines(const char *bus_name, uint8_t dat_lines) "@%s dat_lines: %u"
sdbus_get_cmd_line(const char *bus_name, bool cmd_line) "@%s cmd_line: %u"

# hw/sd/sdhci.c
sdhci_set_inserted(const char *level) "card state changed: %s"
Loading