UART: use new bank API and event manager
[litex.git] / software / libextra / blockdev.c
1 /*
2 * Milkymist SoC (Software)
3 * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <hw/flash.h>
19 #include <hw/memcard.h>
20 #include <string.h>
21
22 #include <blockdev.h>
23
24 //#define MEMCARD_DEBUG
25
26 static void memcard_start_cmd_tx(void)
27 {
28 CSR_MEMCARD_ENABLE = MEMCARD_ENABLE_CMD_TX;
29 }
30
31 static void memcard_start_cmd_rx(void)
32 {
33 CSR_MEMCARD_PENDING = MEMCARD_PENDING_CMD_RX;
34 CSR_MEMCARD_START = MEMCARD_START_CMD_RX;
35 CSR_MEMCARD_ENABLE = MEMCARD_ENABLE_CMD_RX;
36 }
37
38 static void memcard_start_cmd_dat_rx(void)
39 {
40 CSR_MEMCARD_PENDING = MEMCARD_PENDING_CMD_RX|MEMCARD_PENDING_DAT_RX;
41 CSR_MEMCARD_START = MEMCARD_START_CMD_RX|MEMCARD_START_DAT_RX;
42 CSR_MEMCARD_ENABLE = MEMCARD_ENABLE_CMD_RX|MEMCARD_ENABLE_DAT_RX;
43 }
44
45 static void memcard_send_command(unsigned char cmd, unsigned int arg)
46 {
47 unsigned char packet[6];
48 int a;
49 int i;
50 unsigned char data;
51 unsigned char crc;
52
53 packet[0] = cmd | 0x40;
54 packet[1] = ((arg >> 24) & 0xff);
55 packet[2] = ((arg >> 16) & 0xff);
56 packet[3] = ((arg >> 8) & 0xff);
57 packet[4] = (arg & 0xff);
58
59 crc = 0;
60 for(a=0;a<5;a++) {
61 data = packet[a];
62 for(i=0;i<8;i++) {
63 crc <<= 1;
64 if((data & 0x80) ^ (crc & 0x80))
65 crc ^= 0x09;
66 data <<= 1;
67 }
68 }
69 crc = (crc<<1) | 1;
70
71 packet[5] = crc;
72
73 #ifdef MEMCARD_DEBUG
74 printf(">> %02x %02x %02x %02x %02x %02x\n", packet[0], packet[1], packet[2], packet[3], packet[4], packet[5]);
75 #endif
76
77 for(i=0;i<6;i++) {
78 CSR_MEMCARD_CMD = packet[i];
79 while(CSR_MEMCARD_PENDING & MEMCARD_PENDING_CMD_TX);
80 }
81 }
82
83 static void memcard_send_dummy(void)
84 {
85 CSR_MEMCARD_CMD = 0xff;
86 while(CSR_MEMCARD_PENDING & MEMCARD_PENDING_CMD_TX);
87 }
88
89 static int memcard_receive_command(unsigned char *buffer, int len)
90 {
91 int i;
92 int timeout;
93
94 for(i=0;i<len;i++) {
95 timeout = 2000000;
96 while(!(CSR_MEMCARD_PENDING & MEMCARD_PENDING_CMD_RX)) {
97 timeout--;
98 if(timeout == 0) {
99 #ifdef MEMCARD_DEBUG
100 printf("Command receive timeout\n");
101 #endif
102 return 0;
103 }
104 }
105 buffer[i] = CSR_MEMCARD_CMD;
106 CSR_MEMCARD_PENDING = MEMCARD_PENDING_CMD_RX;
107 }
108
109 while(!(CSR_MEMCARD_PENDING & MEMCARD_PENDING_CMD_RX));
110
111 #ifdef MEMCARD_DEBUG
112 printf("<< ");
113 for(i=0;i<len;i++)
114 printf("%02x ", buffer[i]);
115 printf("\n");
116 #endif
117
118 return 1;
119 }
120
121 static int memcard_receive_command_data(unsigned char *command, unsigned int *data)
122 {
123 int i, j;
124 int timeout;
125
126 i = 0;
127 j = 0;
128 while(j < 128) {
129 timeout = 2000000;
130 while(!(CSR_MEMCARD_PENDING & (MEMCARD_PENDING_CMD_RX|MEMCARD_PENDING_DAT_RX))) {
131 timeout--;
132 if(timeout == 0) {
133 #ifdef MEMCARD_DEBUG
134 printf("Command receive timeout\n");
135 #endif
136 return 0;
137 }
138 }
139 if(CSR_MEMCARD_PENDING & MEMCARD_PENDING_CMD_RX) {
140 command[i++] = CSR_MEMCARD_CMD;
141 CSR_MEMCARD_PENDING = MEMCARD_PENDING_CMD_RX;
142 if(i == 6)
143 CSR_MEMCARD_ENABLE = MEMCARD_ENABLE_DAT_RX; /* disable command RX */
144 }
145 if(CSR_MEMCARD_PENDING & MEMCARD_PENDING_DAT_RX) {
146 data[j++] = CSR_MEMCARD_DAT;
147 CSR_MEMCARD_PENDING = MEMCARD_PENDING_DAT_RX;
148 }
149 }
150
151 /* Get CRC (ignored) */
152 for(i=0;i<2;i++) {
153 while(!(CSR_MEMCARD_PENDING & MEMCARD_PENDING_DAT_RX));
154 #ifdef MEMCARD_DEBUG
155 printf("CRC: %08x\n", CSR_MEMCARD_DAT);
156 #endif
157 CSR_MEMCARD_PENDING = MEMCARD_PENDING_DAT_RX;
158 }
159
160 while(!(CSR_MEMCARD_PENDING & MEMCARD_PENDING_DAT_RX));
161
162 #ifdef MEMCARD_DEBUG
163 printf("<< %02x %02x %02x %02x %02x %02x\n", command[0], command[1], command[2], command[3], command[4], command[5]);
164 #endif
165
166 //for(i=0;i<128;i++)
167 // printf("%08x ", data[i]);
168 //printf("\n");
169
170 return 1;
171 }
172
173 static int memcard_init(void)
174 {
175 unsigned char b[17];
176 unsigned int rca;
177
178 CSR_MEMCARD_CLK2XDIV = 250;
179
180 /* CMD0 */
181 memcard_start_cmd_tx();
182 memcard_send_command(0, 0);
183
184 memcard_send_dummy();
185
186 /* CMD8 */
187 memcard_send_command(8, 0x1aa);
188 memcard_start_cmd_rx();
189 if(!memcard_receive_command(b, 6)) return 0;
190
191 /* ACMD41 - initialize */
192 while(1) {
193 memcard_start_cmd_tx();
194 memcard_send_command(55, 0);
195 memcard_start_cmd_rx();
196 if(!memcard_receive_command(b, 6)) return 0;
197 memcard_start_cmd_tx();
198 memcard_send_command(41, 0x00300000);
199 memcard_start_cmd_rx();
200 if(!memcard_receive_command(b, 6)) return 0;
201 if(b[1] & 0x80) break;
202 #ifdef MEMCARD_DEBUG
203 printf("Card is busy, retrying\n");
204 #endif
205 }
206
207 /* CMD2 - get CID */
208 memcard_start_cmd_tx();
209 memcard_send_command(2, 0);
210 memcard_start_cmd_rx();
211 if(!memcard_receive_command(b, 17)) return 0;
212
213 /* CMD3 - get RCA */
214 memcard_start_cmd_tx();
215 memcard_send_command(3, 0);
216 memcard_start_cmd_rx();
217 if(!memcard_receive_command(b, 6)) return 0;
218 rca = (((unsigned int)b[1]) << 8)|((unsigned int)b[2]);
219 #ifdef MEMCARD_DEBUG
220 printf("RCA: %04x\n", rca);
221 #endif
222
223 /* CMD7 - select card */
224 memcard_start_cmd_tx();
225 memcard_send_command(7, rca << 16);
226 memcard_start_cmd_rx();
227 if(!memcard_receive_command(b, 6)) return 0;
228
229 /* ACMD6 - set bus width */
230 memcard_start_cmd_tx();
231 memcard_send_command(55, rca << 16);
232 memcard_start_cmd_rx();
233 if(!memcard_receive_command(b, 6)) return 0;
234 memcard_start_cmd_tx();
235 memcard_send_command(6, 2);
236 memcard_start_cmd_rx();
237 if(!memcard_receive_command(b, 6)) return 0;
238
239 CSR_MEMCARD_CLK2XDIV = 3;
240
241 return 1;
242 }
243
244 static int memcard_readblock(unsigned int block, void *buffer)
245 {
246 unsigned char b[6];
247
248 /* CMD17 - read block */
249 memcard_start_cmd_tx();
250 memcard_send_command(17, block*512);
251 memcard_start_cmd_dat_rx();
252 if(!memcard_receive_command_data(b, (unsigned int *)buffer)) return 0;
253 return 1;
254 }
255
256 int bd_init(int devnr)
257 {
258 return memcard_init();
259 }
260
261 int bd_readblock(unsigned int block, void *buffer)
262 {
263 return memcard_readblock(block, buffer);
264 }
265
266 void bd_done(void)
267 {
268 }
269
270 int bd_has_part_table(int devnr)
271 {
272 return 1;
273 }