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 "hw/sd/sd.h" 25 #include "trace.h" 26 27 static inline const char *sdbus_name(SDBus *sdbus) 28 { 29 return sdbus->qbus.name; 30 } 31 32 static SDState *get_card(SDBus *sdbus) 33 { 34 /* We only ever have one child on the bus so just return it */ 35 BusChild *kid = QTAILQ_FIRST(&sdbus->qbus.children); 36 37 if (!kid) { 38 return NULL; 39 } 40 return SD_CARD(kid->child); 41 } 42 43 uint8_t sdbus_get_dat_lines(SDBus *sdbus) 44 { 45 SDState *slave = get_card(sdbus); 46 uint8_t dat_lines = 0b1111; /* 4 bit bus width */ 47 48 if (slave) { 49 SDCardClass *sc = SD_CARD_GET_CLASS(slave); 50 51 if (sc->get_dat_lines) { 52 dat_lines = sc->get_dat_lines(slave); 53 } 54 } 55 trace_sdbus_get_dat_lines(sdbus_name(sdbus), dat_lines); 56 57 return dat_lines; 58 } 59 60 bool sdbus_get_cmd_line(SDBus *sdbus) 61 { 62 SDState *slave = get_card(sdbus); 63 bool cmd_line = true; 64 65 if (slave) { 66 SDCardClass *sc = SD_CARD_GET_CLASS(slave); 67 68 if (sc->get_cmd_line) { 69 cmd_line = sc->get_cmd_line(slave); 70 } 71 } 72 trace_sdbus_get_cmd_line(sdbus_name(sdbus), cmd_line); 73 74 return cmd_line; 75 } 76 77 void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts) 78 { 79 SDState *card = get_card(sdbus); 80 81 trace_sdbus_set_voltage(sdbus_name(sdbus), millivolts); 82 if (card) { 83 SDCardClass *sc = SD_CARD_GET_CLASS(card); 84 85 assert(sc->set_voltage); 86 sc->set_voltage(card, millivolts); 87 } 88 } 89 90 int sdbus_do_command(SDBus *sdbus, SDRequest *req, uint8_t *response) 91 { 92 SDState *card = get_card(sdbus); 93 94 trace_sdbus_command(sdbus_name(sdbus), req->cmd, req->arg); 95 if (card) { 96 SDCardClass *sc = SD_CARD_GET_CLASS(card); 97 98 return sc->do_command(card, req, response); 99 } 100 101 return 0; 102 } 103 104 void sdbus_write_data(SDBus *sdbus, uint8_t value) 105 { 106 SDState *card = get_card(sdbus); 107 108 trace_sdbus_write(sdbus_name(sdbus), value); 109 if (card) { 110 SDCardClass *sc = SD_CARD_GET_CLASS(card); 111 112 sc->write_data(card, value); 113 } 114 } 115 116 uint8_t sdbus_read_data(SDBus *sdbus) 117 { 118 SDState *card = get_card(sdbus); 119 uint8_t value = 0; 120 121 if (card) { 122 SDCardClass *sc = SD_CARD_GET_CLASS(card); 123 124 value = sc->read_data(card); 125 } 126 trace_sdbus_read(sdbus_name(sdbus), value); 127 128 return value; 129 } 130 131 bool sdbus_data_ready(SDBus *sdbus) 132 { 133 SDState *card = get_card(sdbus); 134 135 if (card) { 136 SDCardClass *sc = SD_CARD_GET_CLASS(card); 137 138 return sc->data_ready(card); 139 } 140 141 return false; 142 } 143 144 bool sdbus_get_inserted(SDBus *sdbus) 145 { 146 SDState *card = get_card(sdbus); 147 148 if (card) { 149 SDCardClass *sc = SD_CARD_GET_CLASS(card); 150 151 return sc->get_inserted(card); 152 } 153 154 return false; 155 } 156 157 bool sdbus_get_readonly(SDBus *sdbus) 158 { 159 SDState *card = get_card(sdbus); 160 161 if (card) { 162 SDCardClass *sc = SD_CARD_GET_CLASS(card); 163 164 return sc->get_readonly(card); 165 } 166 167 return false; 168 } 169 170 void sdbus_set_inserted(SDBus *sdbus, bool inserted) 171 { 172 SDBusClass *sbc = SD_BUS_GET_CLASS(sdbus); 173 BusState *qbus = BUS(sdbus); 174 175 if (sbc->set_inserted) { 176 sbc->set_inserted(qbus->parent, inserted); 177 } 178 } 179 180 void sdbus_set_readonly(SDBus *sdbus, bool readonly) 181 { 182 SDBusClass *sbc = SD_BUS_GET_CLASS(sdbus); 183 BusState *qbus = BUS(sdbus); 184 185 if (sbc->set_readonly) { 186 sbc->set_readonly(qbus->parent, readonly); 187 } 188 } 189 190 void sdbus_reparent_card(SDBus *from, SDBus *to) 191 { 192 SDState *card = get_card(from); 193 SDCardClass *sc; 194 bool readonly; 195 196 /* We directly reparent the card object rather than implementing this 197 * as a hotpluggable connection because we don't want to expose SD cards 198 * to users as being hotpluggable, and we can get away with it in this 199 * limited use case. This could perhaps be implemented more cleanly in 200 * future by adding support to the hotplug infrastructure for "device 201 * can be hotplugged only via code, not by user". 202 */ 203 204 if (!card) { 205 return; 206 } 207 208 sc = SD_CARD_GET_CLASS(card); 209 readonly = sc->get_readonly(card); 210 211 sdbus_set_inserted(from, false); 212 qdev_set_parent_bus(DEVICE(card), &to->qbus); 213 sdbus_set_inserted(to, true); 214 sdbus_set_readonly(to, readonly); 215 } 216 217 static const TypeInfo sd_bus_info = { 218 .name = TYPE_SD_BUS, 219 .parent = TYPE_BUS, 220 .instance_size = sizeof(SDBus), 221 .class_size = sizeof(SDBusClass), 222 }; 223 224 static void sd_bus_register_types(void) 225 { 226 type_register_static(&sd_bus_info); 227 } 228 229 type_init(sd_bus_register_types) 230