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
sdbus_name(SDBus * sdbus)30 static inline const char *sdbus_name(SDBus *sdbus)
31 {
32 return sdbus->qbus.name;
33 }
34
get_card(SDBus * sdbus)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
sdbus_get_dat_lines(SDBus * sdbus)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
sdbus_get_cmd_line(SDBus * sdbus)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
sdbus_set_voltage(SDBus * sdbus,uint16_t millivolts)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
sdbus_do_command(SDBus * sdbus,SDRequest * req,uint8_t * resp,size_t respsz)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
sdbus_write_byte(SDBus * sdbus,uint8_t value)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
sdbus_write_data(SDBus * sdbus,const void * buf,size_t length)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
sdbus_read_byte(SDBus * sdbus)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
sdbus_read_data(SDBus * sdbus,void * buf,size_t length)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
sdbus_receive_ready(SDBus * sdbus)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
sdbus_data_ready(SDBus * sdbus)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
sdbus_get_inserted(SDBus * sdbus)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
sdbus_get_readonly(SDBus * sdbus)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
sdbus_set_inserted(SDBus * sdbus,bool inserted)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
sdbus_set_readonly(SDBus * sdbus,bool readonly)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
sdbus_reparent_card(SDBus * from,SDBus * to)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