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