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 * response)93 int sdbus_do_command(SDBus *sdbus, SDRequest *req, uint8_t *response)
94 {
95 SDState *card = get_card(sdbus);
96
97 trace_sdbus_command(sdbus_name(sdbus), req->cmd, req->arg);
98 if (card) {
99 SDCardClass *sc = SDMMC_COMMON_GET_CLASS(card);
100
101 return sc->do_command(card, req, response);
102 }
103
104 return 0;
105 }
106
sdbus_write_byte(SDBus * sdbus,uint8_t value)107 void sdbus_write_byte(SDBus *sdbus, uint8_t value)
108 {
109 SDState *card = get_card(sdbus);
110
111 trace_sdbus_write(sdbus_name(sdbus), value);
112 if (card) {
113 SDCardClass *sc = SDMMC_COMMON_GET_CLASS(card);
114
115 sc->write_byte(card, value);
116 }
117 }
118
sdbus_write_data(SDBus * sdbus,const void * buf,size_t length)119 void sdbus_write_data(SDBus *sdbus, const void *buf, size_t length)
120 {
121 SDState *card = get_card(sdbus);
122 const uint8_t *data = buf;
123
124 if (card) {
125 SDCardClass *sc = SDMMC_COMMON_GET_CLASS(card);
126
127 for (size_t i = 0; i < length; i++) {
128 trace_sdbus_write(sdbus_name(sdbus), data[i]);
129 sc->write_byte(card, data[i]);
130 }
131 }
132 }
133
sdbus_read_byte(SDBus * sdbus)134 uint8_t sdbus_read_byte(SDBus *sdbus)
135 {
136 SDState *card = get_card(sdbus);
137 uint8_t value = 0;
138
139 if (card) {
140 SDCardClass *sc = SDMMC_COMMON_GET_CLASS(card);
141
142 value = sc->read_byte(card);
143 }
144 trace_sdbus_read(sdbus_name(sdbus), value);
145
146 return value;
147 }
148
sdbus_read_data(SDBus * sdbus,void * buf,size_t length)149 void sdbus_read_data(SDBus *sdbus, void *buf, size_t length)
150 {
151 SDState *card = get_card(sdbus);
152 uint8_t *data = buf;
153
154 if (card) {
155 SDCardClass *sc = SDMMC_COMMON_GET_CLASS(card);
156
157 for (size_t i = 0; i < length; i++) {
158 data[i] = sc->read_byte(card);
159 trace_sdbus_read(sdbus_name(sdbus), data[i]);
160 }
161 }
162 }
163
sdbus_receive_ready(SDBus * sdbus)164 bool sdbus_receive_ready(SDBus *sdbus)
165 {
166 SDState *card = get_card(sdbus);
167
168 if (card) {
169 SDCardClass *sc = SDMMC_COMMON_GET_CLASS(card);
170
171 return sc->receive_ready(card);
172 }
173
174 return false;
175 }
176
sdbus_data_ready(SDBus * sdbus)177 bool sdbus_data_ready(SDBus *sdbus)
178 {
179 SDState *card = get_card(sdbus);
180
181 if (card) {
182 SDCardClass *sc = SDMMC_COMMON_GET_CLASS(card);
183
184 return sc->data_ready(card);
185 }
186
187 return false;
188 }
189
sdbus_get_inserted(SDBus * sdbus)190 bool sdbus_get_inserted(SDBus *sdbus)
191 {
192 SDState *card = get_card(sdbus);
193
194 if (card) {
195 SDCardClass *sc = SDMMC_COMMON_GET_CLASS(card);
196
197 return sc->get_inserted(card);
198 }
199
200 return false;
201 }
202
sdbus_get_readonly(SDBus * sdbus)203 bool sdbus_get_readonly(SDBus *sdbus)
204 {
205 SDState *card = get_card(sdbus);
206
207 if (card) {
208 SDCardClass *sc = SDMMC_COMMON_GET_CLASS(card);
209
210 return sc->get_readonly(card);
211 }
212
213 return false;
214 }
215
sdbus_set_inserted(SDBus * sdbus,bool inserted)216 void sdbus_set_inserted(SDBus *sdbus, bool inserted)
217 {
218 SDBusClass *sbc = SD_BUS_GET_CLASS(sdbus);
219 BusState *qbus = BUS(sdbus);
220
221 if (sbc->set_inserted) {
222 sbc->set_inserted(qbus->parent, inserted);
223 }
224 }
225
sdbus_set_readonly(SDBus * sdbus,bool readonly)226 void sdbus_set_readonly(SDBus *sdbus, bool readonly)
227 {
228 SDBusClass *sbc = SD_BUS_GET_CLASS(sdbus);
229 BusState *qbus = BUS(sdbus);
230
231 if (sbc->set_readonly) {
232 sbc->set_readonly(qbus->parent, readonly);
233 }
234 }
235
sdbus_reparent_card(SDBus * from,SDBus * to)236 void sdbus_reparent_card(SDBus *from, SDBus *to)
237 {
238 SDState *card = get_card(from);
239 SDCardClass *sc;
240 bool readonly;
241
242 /* We directly reparent the card object rather than implementing this
243 * as a hotpluggable connection because we don't want to expose SD cards
244 * to users as being hotpluggable, and we can get away with it in this
245 * limited use case. This could perhaps be implemented more cleanly in
246 * future by adding support to the hotplug infrastructure for "device
247 * can be hotplugged only via code, not by user".
248 */
249
250 if (!card) {
251 return;
252 }
253
254 sc = SDMMC_COMMON_GET_CLASS(card);
255 readonly = sc->get_readonly(card);
256
257 sdbus_set_inserted(from, false);
258 qdev_set_parent_bus(DEVICE(card), &to->qbus, &error_abort);
259 sdbus_set_inserted(to, true);
260 sdbus_set_readonly(to, readonly);
261 }
262
263 static const TypeInfo sd_bus_types[] = {
264 {
265 .name = TYPE_SD_BUS,
266 .parent = TYPE_BUS,
267 .instance_size = sizeof(SDBus),
268 .class_size = sizeof(SDBusClass),
269 },
270 };
271
272 DEFINE_TYPES(sd_bus_types)
273