qemu/hw/sd/core.c
<<
>>
Prefs
   1/*
   2 * SD card bus interface code.
   3 *
   4 * Copyright (c) 2015 Linaro Limited
   5 *
   6 * Author:
   7 *  Peter Maydell <peter.maydell@linaro.org>
   8 *
   9 * This program is free software; you can redistribute it and/or modify it
  10 * under the terms and conditions of the GNU General Public License,
  11 * version 2 or later, as published by the Free Software Foundation.
  12 *
  13 * This program is distributed in the hope it will be useful, but WITHOUT
  14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  16 * more details.
  17 *
  18 * You should have received a copy of the GNU General Public License along with
  19 * this program.  If not, see <http://www.gnu.org/licenses/>.
  20 */
  21
  22#include "qemu/osdep.h"
  23#include "hw/qdev-core.h"
  24#include "sysemu/block-backend.h"
  25#include "hw/sd/sd.h"
  26
  27static SDState *get_card(SDBus *sdbus)
  28{
  29    /* We only ever have one child on the bus so just return it */
  30    BusChild *kid = QTAILQ_FIRST(&sdbus->qbus.children);
  31
  32    if (!kid) {
  33        return NULL;
  34    }
  35    return SD_CARD(kid->child);
  36}
  37
  38uint8_t sdbus_get_dat_lines(SDBus *sdbus)
  39{
  40    SDState *card = get_card(sdbus);
  41
  42    if (card) {
  43        SDCardClass *sc = SD_CARD_GET_CLASS(card);
  44
  45        return sc->get_dat_lines(card);
  46    }
  47
  48    return 0;
  49}
  50
  51bool sdbus_get_cmd_line(SDBus *sdbus)
  52{
  53    SDState *card = get_card(sdbus);
  54
  55    if (card) {
  56        SDCardClass *sc = SD_CARD_GET_CLASS(card);
  57
  58        return sc->get_cmd_line(card);
  59    }
  60
  61    return false;
  62}
  63
  64void sdbus_set_voltage(SDBus *sdbus, int v)
  65{
  66    SDState *card = get_card(sdbus);
  67
  68    if (card) {
  69        SDCardClass *sc = SD_CARD_GET_CLASS(card);
  70
  71        sc->set_voltage(card, v);
  72    }
  73}
  74
  75int sdbus_do_command(SDBus *sdbus, SDRequest *req, uint8_t *response)
  76{
  77    SDState *card = get_card(sdbus);
  78
  79    if (card) {
  80        SDCardClass *sc = SD_CARD_GET_CLASS(card);
  81
  82        return sc->do_command(card, req, response);
  83    }
  84
  85    return 0;
  86}
  87
  88void sdbus_write_data(SDBus *sdbus, uint8_t value)
  89{
  90    SDState *card = get_card(sdbus);
  91
  92    if (card) {
  93        SDCardClass *sc = SD_CARD_GET_CLASS(card);
  94
  95        sc->write_data(card, value);
  96    }
  97}
  98
  99uint8_t sdbus_read_data(SDBus *sdbus)
 100{
 101    SDState *card = get_card(sdbus);
 102
 103    if (card) {
 104        SDCardClass *sc = SD_CARD_GET_CLASS(card);
 105
 106        return sc->read_data(card);
 107    }
 108
 109    return 0;
 110}
 111
 112bool sdbus_data_ready(SDBus *sdbus)
 113{
 114    SDState *card = get_card(sdbus);
 115
 116    if (card) {
 117        SDCardClass *sc = SD_CARD_GET_CLASS(card);
 118
 119        return sc->data_ready(card);
 120    }
 121
 122    return false;
 123}
 124
 125bool sdbus_get_inserted(SDBus *sdbus)
 126{
 127    SDState *card = get_card(sdbus);
 128
 129    if (card) {
 130        SDCardClass *sc = SD_CARD_GET_CLASS(card);
 131
 132        return sc->get_inserted(card);
 133    }
 134
 135    return false;
 136}
 137
 138bool sdbus_get_readonly(SDBus *sdbus)
 139{
 140    SDState *card = get_card(sdbus);
 141
 142    if (card) {
 143        SDCardClass *sc = SD_CARD_GET_CLASS(card);
 144
 145        return sc->get_readonly(card);
 146    }
 147
 148    return false;
 149}
 150
 151void sdbus_set_inserted(SDBus *sdbus, bool inserted)
 152{
 153    SDBusClass *sbc = SD_BUS_GET_CLASS(sdbus);
 154    BusState *qbus = BUS(sdbus);
 155
 156    if (sbc->set_inserted) {
 157        sbc->set_inserted(qbus->parent, inserted);
 158    }
 159}
 160
 161void sdbus_set_readonly(SDBus *sdbus, bool readonly)
 162{
 163    SDBusClass *sbc = SD_BUS_GET_CLASS(sdbus);
 164    BusState *qbus = BUS(sdbus);
 165
 166    if (sbc->set_readonly) {
 167        sbc->set_readonly(qbus->parent, readonly);
 168    }
 169}
 170
 171static const TypeInfo sd_bus_info = {
 172    .name = TYPE_SD_BUS,
 173    .parent = TYPE_BUS,
 174    .instance_size = sizeof(SDBus),
 175    .class_size = sizeof(SDBusClass),
 176};
 177
 178static void sd_bus_register_types(void)
 179{
 180    type_register_static(&sd_bus_info);
 181}
 182
 183type_init(sd_bus_register_types)
 184