1 // Copyright 2008 Haxx Enterprises <bushing@gmail.com>
2 // Copyright 2008-2009 Segher Boessenkool <segher@kernel.crashing.org>
3 // This code is licensed to you under the terms of the GNU GPL, version 2;
4 // see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
11 static u32 rca; // 16 bottom bits are stuff bits
14 static int sd_hc_write8(u8 reg, u8 data)
19 memset(param, 0, sizeof param);
21 param[3] = 1; // reg size
24 err = ios_ioctl(fd, 1, param, sizeof param, 0, 0);
29 static int sd_hc_read8(u8 reg, u8 *x)
35 memset(param, 0, sizeof param);
37 param[3] = 1; // reg size
40 err = ios_ioctl(fd, 2, param, sizeof param, &data, sizeof data);
49 static int sd_reset_card(void)
54 err = ios_ioctl(fd, 4, 0, 0, &reply, sizeof reply);
58 rca = reply & 0xffff0000;
60 // printf("sd_reset_card(): got reply = %08x\n", reply);
65 static int sd_set_clock(void)
70 clock = 1; // half of the sdclk divisor: a power of two or zero,
71 // should look at capabilities reg to compute this
73 err = ios_ioctl(fd, 6, &clock, sizeof clock, 0, 0);
78 static int sd_command(u32 cmd, u32 cmd_type, u32 resp_type, u32 arg,
79 u32 block_count, u32 block_size, void *addr,
80 u32 *outreply, u32 reply_size)
90 param[4] = block_count;
91 param[5] = block_size;
96 err = ios_ioctl(fd, 7, param, sizeof param, reply, sizeof reply);
98 if (reply_size) // ???
99 memcpy(outreply, reply, reply_size);
110 #define RESPONSE_NONE 0
111 #define RESPONSE_R1 1
112 #define RESPONSE_R1B 2
113 #define RESPONSE_R2 3
114 #define RESPONSE_R3 4
115 #define RESPONSE_R4 5
116 #define RESPONSE_R5 6
117 #define RESPONSE_R6 7
120 static int sd_app_command(u32 cmd, u32 cmd_type, u32 resp_type, u32 arg,
121 u32 block_count, u32 block_size, void *addr,
122 u32 *outreply, u32 reply_size)
126 err = sd_command(55, TYPE_AC, RESPONSE_R1, rca, 0, 0, 0, 0, 0);
130 err = sd_command(cmd, cmd_type, resp_type, arg,
131 block_count, block_size, addr,
132 outreply, reply_size);
137 static int sd_data_command(u32 cmd, u32 cmd_type, u32 resp_type, u32 arg,
138 u32 block_count, u32 block_size, void *data,
139 u32 unk1, u32 unk2, u32 *outreply, u32 reply_size)
143 struct ioctlv vec[3];
148 param[2] = resp_type;
150 param[4] = block_count;
151 param[5] = block_size;
152 param[6] = (u32)data;
153 param[7] = unk1; // ???
154 param[8] = unk2; // ???
157 vec[0].len = sizeof param;
159 vec[1].len = block_count * block_size;
161 vec[2].len = sizeof reply;
163 err = ios_ioctlv(fd, 7, 2, 1, vec);
165 if (reply_size) // ???
166 memcpy(outreply, reply, reply_size);
171 static int sd_select(void)
175 //printf("Selecting card:\n");
176 err = sd_command(7, TYPE_AC, RESPONSE_R1B, rca, 0, 0, 0, 0, 0);
181 static int sd_set_blocklength(u32 len)
185 //printf("sd_set_blocklength(%u)\n", len);
186 err = sd_command(16, TYPE_AC, RESPONSE_R1, len, 0, 0, 0, 0, 0);
191 static int sd_set_bus_width(int width)
197 // First notify the card.
198 arg = (width == 4) ? 2 : 0;
199 //printf("sd_set_bus_width()\n");
200 err = sd_app_command(6, TYPE_AC, RESPONSE_R1, arg, 0, 0, 0, 0, 0);
204 // Now change the Host Control Register.
205 err = sd_hc_read8(0x28, ®);
209 reg = (reg & ~2) | arg;
211 err = sd_hc_write8(0x28, reg);
216 int sd_read_sector(u8 *data, u32 offset)
221 if (offset >= 0x800000)
224 err = sd_data_command(18, TYPE_AC, RESPONSE_R1, 0x200 * offset,
225 1, 0x200, data, 1, 0, reply, sizeof reply);
227 sync_before_read(data, 0x200);
229 //printf("READ block %d\r",offset);
231 printf("SD READ %d: err=%08x, reply=%08x %08x %08x %08x\n",
232 offset, err, reply[0], reply[1], reply[2], reply[3]);
239 return ios_close(fd);
246 fd = ios_open("/dev/sdio/slot0", 0);
250 err = sd_reset_card();
252 printf("SD Card not present? (%d)\n", err);
256 // now in standby state
262 // now in transfer state
264 // Some broken cards require this:
265 err = sd_set_blocklength(0x200);
269 err = sd_set_bus_width(4); // XXX: Should check in SCR first.
273 err = sd_set_clock(); // XXX: Should check.