source: rtems/c/src/libchip/i2c/spi-sd-card.c @ 4c18d8c

4.104.115
Last change on this file since 4c18d8c was 4c18d8c, checked in by Joel Sherrill <joel.sherrill@…>, on 01/21/09 at 18:08:32

2009-01-21 Sebastian Huber <sebastian.huber@…>

  • libchip/i2c/spi-sd-card.h, libchip/i2c/spi-sd-card.c: Fixed RTEMS_BLKDEV_CAPABILITIES ioctl which caused invalid multiple block writes. Fixed integer type in device structure.
  • Property mode set to 100644
File size: 27.6 KB
Line 
1/**
2 * @file
3 *
4 * @brief SD Card LibI2C driver.
5 */
6
7/*
8 * Copyright (c) 2008
9 * Embedded Brains GmbH
10 * Obere Lagerstr. 30
11 * D-82178 Puchheim
12 * Germany
13 * rtems@embedded-brains.de
14 *
15 * The license and distribution terms for this file may be found in the file
16 * LICENSE in this distribution or at http://www.rtems.com/license/LICENSE.
17 */
18
19#include <stdio.h>
20#include <errno.h>
21#include <inttypes.h>
22
23#include <rtems.h>
24#include <rtems/libi2c.h>
25#include <rtems/libio.h>
26#include <rtems/diskdevs.h>
27
28#include <libchip/spi-sd-card.h>
29
30#include <rtems/status-checks.h>
31
32/**
33 * @name Integer to and from Byte-Stream Converter
34 * @{
35 */
36
37static inline uint16_t sd_card_get_uint16( const uint8_t *s)
38{
39        return (uint16_t) ((s [0] << 8) | s [1]);
40}
41
42static inline uint32_t sd_card_get_uint32( const uint8_t *s)
43{
44        return ((uint32_t) s [0] << 24) | ((uint32_t) s [1] << 16) | ((uint32_t) s [2] << 8) | (uint32_t) s [3];
45}
46
47static inline void sd_card_put_uint16( uint16_t v, uint8_t *s)
48{
49        *s++ = (uint8_t) (v >> 8);
50        *s   = (uint8_t) (v);
51}
52
53static inline void sd_card_put_uint32( uint32_t v, uint8_t *s)
54{
55        *s++ = (uint8_t) (v >> 24);
56        *s++ = (uint8_t) (v >> 16);
57        *s++ = (uint8_t) (v >> 8);
58        *s   = (uint8_t) (v);
59}
60
61/** @} */
62
63#define SD_CARD_BUSY_TOKEN 0
64
65#define SD_CARD_BLOCK_SIZE_DEFAULT 512
66
67#define SD_CARD_COMMAND_RESPONSE_START 7
68
69/**
70 * @name Commands
71 * @{
72 */
73
74#define SD_CARD_CMD_GO_IDLE_STATE 0
75#define SD_CARD_CMD_SEND_OP_COND 1
76#define SD_CARD_CMD_SEND_CSD 9
77#define SD_CARD_CMD_SEND_CID 10
78#define SD_CARD_CMD_STOP_TRANSMISSION 12
79#define SD_CARD_CMD_SEND_STATUS 13
80#define SD_CARD_CMD_SET_BLOCKLEN 16
81#define SD_CARD_CMD_READ_SINGLE_BLOCK 17
82#define SD_CARD_CMD_READ_MULTIPLE_BLOCK 18
83#define SD_CARD_CMD_SET_BLOCK_COUNT 23
84#define SD_CARD_CMD_WRITE_BLOCK 24
85#define SD_CARD_CMD_WRITE_MULTIPLE_BLOCK 25
86#define SD_CARD_CMD_PROGRAM_CSD 27
87#define SD_CARD_CMD_SET_WRITE_PROT 28
88#define SD_CARD_CMD_CLR_WRITE_PROT 29
89#define SD_CARD_CMD_SEND_WRITE_PROT 30
90#define SD_CARD_CMD_TAG_SECTOR_START 32
91#define SD_CARD_CMD_TAG_SECTOR_END 33
92#define SD_CARD_CMD_UNTAG_SECTOR 34
93#define SD_CARD_CMD_TAG_ERASE_GROUP_START 35
94#define SD_CARD_CMD_TAG_ERASE_GROUP_END 36
95#define SD_CARD_CMD_UNTAG_ERASE_GROUP 37
96#define SD_CARD_CMD_ERASE 38
97#define SD_CARD_CMD_LOCK_UNLOCK 42
98#define SD_CARD_CMD_APP_CMD 55
99#define SD_CARD_CMD_GEN_CND 56
100#define SD_CARD_CMD_READ_OCR 58
101#define SD_CARD_CMD_CRC_ON_OFF 59
102
103/** @} */
104
105/**
106 * @name Application Commands
107 * @{
108 */
109
110#define SD_CARD_ACMD_SD_SEND_OP_COND 41
111
112/** @} */
113
114/**
115 * @name Command Fields
116 * @{
117 */
118
119#define SD_CARD_COMMAND_SET_COMMAND( c, cmd) (c) [1] = (uint8_t) (0x40 + ((cmd) & 0x3f))
120#define SD_CARD_COMMAND_SET_ARGUMENT( c, arg) sd_card_put_uint32( (arg), &((c) [2]))
121#define SD_CARD_COMMAND_SET_CRC7( c, crc7) ((c) [6] = (crc7) << 1)
122
123#define SD_CARD_COMMAND_GET_CRC7( c) ((c) [6] >> 1)
124
125/** @} */
126
127/**
128 * @name Response Fields
129 * @{
130 */
131
132#define SD_CARD_IS_RESPONSE( r) (((r) & 0x80) == 0)
133
134#define SD_CARD_IS_ERRORLESS_RESPONSE( r) (((r) & 0x7e) == 0)
135
136#define SD_CARD_IS_NOT_IDLE_RESPONSE( r) (((r) & 0x81) == 0)
137
138#define SD_CARD_IS_DATA_ERROR( r) (((r) & 0xe0) == 0)
139
140#define SD_CARD_IS_DATA_REJECTED( r) (((r) & 0x1f) != 0x05)
141
142/** @} */
143
144/**
145 * @name Card Identification
146 * @{
147 */
148
149#define SD_CARD_CID_SIZE 16
150
151#define SD_CARD_CID_GET_MID( cid) ((cid) [0])
152#define SD_CARD_CID_GET_OID( cid) sd_card_get_uint16( cid + 1)
153#define SD_CARD_CID_GET_PNM( cid, i) ((char) (cid) [3 + (i)])
154#define SD_CARD_CID_GET_PRV( cid) ((cid) [9])
155#define SD_CARD_CID_GET_PSN( cid) sd_card_get_uint32( cid + 10)
156#define SD_CARD_CID_GET_MDT( cid) ((cid) [14])
157#define SD_CARD_CID_GET_CRC7( cid) ((cid) [15] >> 1)
158
159/** @} */
160
161/**
162 * @name Card Specific Data
163 * @{
164 */
165
166#define SD_CARD_CSD_SIZE 16
167
168#define SD_CARD_CSD_GET_CSD_STRUCTURE( csd) ((csd) [0] >> 6)
169#define SD_CARD_CSD_GET_SPEC_VERS( csd) (((csd) [0] >> 2) & 0xf)
170#define SD_CARD_CSD_GET_TAAC( csd) ((csd) [1])
171#define SD_CARD_CSD_GET_NSAC( csd) ((uint32_t) (csd) [2])
172#define SD_CARD_CSD_GET_TRAN_SPEED( csd) ((csd) [3])
173#define SD_CARD_CSD_GET_C_SIZE( csd) ((((uint32_t) (csd) [6] & 0x3) << 10) + ((uint32_t) (csd) [7] << 2) + (((uint32_t) (csd) [8] >> 6) & 0x3))
174#define SD_CARD_CSD_GET_C_SIZE_MULT( csd) ((((csd) [9] & 0x3) << 1) + (((csd) [10] >> 7) & 0x1))
175#define SD_CARD_CSD_GET_READ_BLK_LEN( csd) ((uint32_t) (csd) [5] & 0xf)
176#define SD_CARD_CSD_GET_WRITE_BLK_LEN( csd) ((((csd) [12] & 0x3) << 2) + (((csd) [13] >> 6) & 0x3))
177
178/** @} */
179
180#define SD_CARD_INVALIDATE_RESPONSE_INDEX( e) e->response_index = SD_CARD_COMMAND_SIZE
181
182/**
183 * @name Data Start and Stop Tokens
184 * @{
185 */
186
187#define SD_CARD_START_BLOCK_SINGLE_BLOCK_READ 0xfe
188#define SD_CARD_START_BLOCK_MULTIPLE_BLOCK_READ 0xfe
189#define SD_CARD_START_BLOCK_SINGLE_BLOCK_WRITE 0xfe
190#define SD_CARD_START_BLOCK_MULTIPLE_BLOCK_WRITE 0xfc
191#define SD_CARD_STOP_TRANSFER_MULTIPLE_BLOCK_WRITE 0xfd
192
193/** @} */
194
195/**
196 * @name Card Specific Data Functions
197 * @{
198 */
199
200static inline uint32_t sd_card_block_number( const uint8_t *csd)
201{
202        uint32_t size = SD_CARD_CSD_GET_C_SIZE( csd);
203        uint32_t mult = 1U << (SD_CARD_CSD_GET_C_SIZE_MULT( csd) + 2);
204        return (size + 1) * mult;
205}
206
207static inline uint32_t sd_card_capacity( const uint8_t *csd)
208{
209        uint32_t block_size = 1U << SD_CARD_CSD_GET_READ_BLK_LEN( csd);
210        return sd_card_block_number( csd) * block_size;
211}
212
213static inline uint32_t sd_card_transfer_speed( const uint8_t *csd)
214{
215        uint32_t s = SD_CARD_CSD_GET_TRAN_SPEED( csd);
216        uint32_t e = s & 0x7;
217        uint32_t m = s >> 3;
218        switch (e) {
219                case 0: s = 10000; break;
220                case 1: s = 100000; break;
221                case 2: s = 1000000; break;
222                case 3: s = 10000000; break;
223                default: s = 0; break;
224        }
225        switch (m) {
226                case 1: s *= 10; break;
227                case 2: s *= 12; break;
228                case 3: s *= 13; break;
229                case 4: s *= 15; break;
230                case 5: s *= 20; break;
231                case 6: s *= 25; break;
232                case 7: s *= 30; break;
233                case 8: s *= 35; break;
234                case 9: s *= 40; break;
235                case 10: s *= 45; break;
236                case 11: s *= 50; break;
237                case 12: s *= 55; break;
238                case 13: s *= 60; break;
239                case 14: s *= 70; break;
240                case 15: s *= 80; break;
241                default: s *= 0; break;
242        }
243        return s;
244}
245
246static inline uint32_t sd_card_access_time( const uint8_t *csd)
247{
248        uint32_t ac = SD_CARD_CSD_GET_TAAC( csd);
249        uint32_t e = ac & 0x7;
250        uint32_t m = ac >> 3;
251        switch (e) {
252                case 0: ac = 1; break;
253                case 1: ac = 10; break;
254                case 2: ac = 100; break;
255                case 3: ac = 1000; break;
256                case 4: ac = 10000; break;
257                case 5: ac = 100000; break;
258                case 6: ac = 1000000; break;
259                case 7: ac = 10000000; break;
260                default: ac = 0; break;
261        }
262        switch (m) {
263                case 1: ac *= 10; break;
264                case 2: ac *= 12; break;
265                case 3: ac *= 13; break;
266                case 4: ac *= 15; break;
267                case 5: ac *= 20; break;
268                case 6: ac *= 25; break;
269                case 7: ac *= 30; break;
270                case 8: ac *= 35; break;
271                case 9: ac *= 40; break;
272                case 10: ac *= 45; break;
273                case 11: ac *= 50; break;
274                case 12: ac *= 55; break;
275                case 13: ac *= 60; break;
276                case 14: ac *= 70; break;
277                case 15: ac *= 80; break;
278                default: ac *= 0; break;
279        }
280        return ac / 10;
281}
282
283static inline uint32_t sd_card_max_access_time( const uint8_t *csd, uint32_t transfer_speed)
284{
285        uint64_t ac = sd_card_access_time( csd);
286        uint32_t n = SD_CARD_CSD_GET_NSAC( csd) * 100;
287        ac = (ac * transfer_speed) / 8000000000ULL;
288        return n + (uint32_t) ac;
289}
290
291/** @} */
292
293/**
294 * @name Communication Functions
295 * @{
296 */
297
298static inline int sd_card_query( sd_card_driver_entry *e, uint8_t *in, int n)
299{
300        return rtems_libi2c_read_bytes( e->bus, in, n);
301}
302
303static int sd_card_wait( sd_card_driver_entry *e)
304{
305        int rv = 0;
306        int r = 0;
307        int n = 2;
308        while (e->busy) {
309                /* Query busy tokens */
310                rv = sd_card_query( e, e->response, n);
311                RTEMS_CHECK_RV( rv, "Busy");
312
313                /* Search for non busy tokens */
314                for (r = 0; r < n; ++r) {
315                        if (e->response [r] != SD_CARD_BUSY_TOKEN) {
316                                e->busy = false;
317                                return 0;
318                        }
319                }
320                n = SD_CARD_COMMAND_SIZE;
321
322                if (e->schedule_if_busy) {
323                        /* Invoke the scheduler */
324                        rtems_task_wake_after( RTEMS_YIELD_PROCESSOR);
325                }
326        }
327        return 0;
328}
329
330static int sd_card_send_command( sd_card_driver_entry *e, uint32_t command, uint32_t argument)
331{
332        int rv = 0;
333        rtems_libi2c_read_write_t rw = {
334                .rd_buf = e->response,
335                .wr_buf = e->command,
336                .byte_cnt = SD_CARD_COMMAND_SIZE
337        };
338        int r = 0;
339
340        SD_CARD_INVALIDATE_RESPONSE_INDEX( e);
341
342        /* Wait until card is not busy */
343        rv = sd_card_wait( e);
344        RTEMS_CHECK_RV( rv, "Wait");
345
346        /* Write command and read response */
347        SD_CARD_COMMAND_SET_COMMAND( e->command, command);
348        SD_CARD_COMMAND_SET_ARGUMENT( e->command, argument);
349        rv = rtems_libi2c_ioctl( e->bus, RTEMS_LIBI2C_IOCTL_READ_WRITE, &rw);
350        RTEMS_CHECK_RV( rv, "Write command and read response");
351
352        /* Check respose */
353        for (r = SD_CARD_COMMAND_RESPONSE_START; r < SD_CARD_COMMAND_SIZE; ++r) {
354                RTEMS_DEBUG_PRINT( "Token [%02u]: 0x%02x\n", r, e->response [r]);
355                e->response_index = r;
356                if (SD_CARD_IS_RESPONSE( e->response [r])) {
357                        if (SD_CARD_IS_ERRORLESS_RESPONSE( e->response [r])) {
358                                return 0;
359                        } else {
360                                RTEMS_SYSLOG_ERROR( "Command error [%02i]: 0x%02" PRIx8 "\n", r, e->response [r]);
361                                goto sd_card_send_command_error;
362                        }
363                } else if (e->response [r] != SD_CARD_IDLE_TOKEN) {
364                        RTEMS_SYSLOG_ERROR( "Unexpected token [%02i]: 0x%02" PRIx8 "\n", r, e->response [r]);
365                        goto sd_card_send_command_error;
366                }
367        }
368
369        RTEMS_SYSLOG_ERROR( "Timeout\n");
370
371sd_card_send_command_error:
372
373        RTEMS_SYSLOG_ERROR( "Response:");
374        for (r = 0; r < SD_CARD_COMMAND_SIZE; ++r) {
375                if (e->response_index == r) {
376                        RTEMS_SYSLOG_PRINT( " %02" PRIx8 ":[%02" PRIx8 "]", e->command [r], e->response [r]);
377                } else {
378                        RTEMS_SYSLOG_PRINT( " %02" PRIx8 ":%02" PRIx8 "", e->command [r], e->response [r]);
379                }
380        }
381        RTEMS_SYSLOG_PRINT( "\n");
382
383        return -RTEMS_IO_ERROR;
384}
385
386static int sd_card_stop_multiple_block_read( sd_card_driver_entry *e)
387{
388        int rv = 0;
389
390        SD_CARD_COMMAND_SET_COMMAND( e->command, SD_CARD_CMD_STOP_TRANSMISSION);
391        rv = rtems_libi2c_write_bytes( e->bus, e->command, SD_CARD_COMMAND_SIZE);
392        RTEMS_CHECK_RV( rv, "Write stop transfer token");
393
394        return 0;
395}
396
397static int sd_card_stop_multiple_block_write( sd_card_driver_entry *e)
398{
399        int rv = 0;
400        uint8_t stop_transfer [3] = { SD_CARD_IDLE_TOKEN, SD_CARD_STOP_TRANSFER_MULTIPLE_BLOCK_WRITE, SD_CARD_IDLE_TOKEN };
401
402        /* Wait until card is not busy */
403        rv = sd_card_wait( e);
404        RTEMS_CHECK_RV( rv, "Wait");
405
406        /* Send stop token */
407        rv = rtems_libi2c_write_bytes( e->bus, stop_transfer, 3);
408        RTEMS_CHECK_RV( rv, "Write stop transfer token");
409
410        /* Card is now busy */
411        e->busy = true;
412
413        return 0;
414}
415
416static int sd_card_read( sd_card_driver_entry *e, uint8_t start_token, uint8_t *in, int n)
417{
418        int rv = 0;
419
420        /* Access time idle tokens */
421        uint32_t n_ac = 1;
422
423        /* Discard command response */
424        int r = e->response_index + 1;
425
426        /* Minimum token number before data start */
427        int next_response_size = 2;
428
429        /* Standard response size */
430        int response_size = SD_CARD_COMMAND_SIZE;
431
432        /* Data input index */
433        int i = 0;
434
435        SD_CARD_INVALIDATE_RESPONSE_INDEX( e);
436
437        while (true) {
438                RTEMS_DEBUG_PRINT( "Search from %u to %u\n", r, response_size - 1);
439
440                /* Search the data start token in in current response buffer */
441                while (r < response_size) {
442                        RTEMS_DEBUG_PRINT( "Token [%02u]: 0x%02x\n", r, e->response [r]);
443                        if (n_ac > e->n_ac_max) {
444                                RTEMS_SYSLOG_ERROR( "Timeout\n");
445                                return -RTEMS_IO_ERROR;
446                        } else if (e->response [r] == start_token) {
447                                /* Discard data start token */
448                                ++r;
449                                goto sd_card_read_start;
450                        } else if (SD_CARD_IS_DATA_ERROR( e->response [r])) {
451                                RTEMS_SYSLOG_ERROR( "Data error token [%02i]: 0x%02" PRIx8 "\n", r, e->response [r]);
452                                return -RTEMS_IO_ERROR;
453                        } else if (e->response [r] != SD_CARD_IDLE_TOKEN) {
454                                RTEMS_SYSLOG_ERROR( "Unexpected token [%02i]: 0x%02" PRIx8 "\n", r, e->response [r]);
455                                return -RTEMS_IO_ERROR;
456                        }
457                        ++n_ac;
458                        ++r;
459                }
460
461                /* Query more */
462                rv = sd_card_query( e, e->response, next_response_size);
463                RTEMS_CHECK_RV( rv, "Query data start token");
464
465                /* Set standard query size */
466                response_size = next_response_size;
467                next_response_size = SD_CARD_COMMAND_SIZE;
468
469                /* Reset start position */
470                r = 0;
471        }
472
473sd_card_read_start:
474
475        /* Read data */
476        while (r < response_size && i < n) {
477                in [i++] = e->response [r++];
478        }
479
480        /* Read more data? */
481        if (i < n) {
482                rv = sd_card_query( e, &in [i], n - i);
483                RTEMS_CHECK_RV( rv, "Read data");
484                i += rv;
485        }
486
487        /* Read CRC 16 and N_RC */
488        rv = sd_card_query( e, e->response, 3);
489        RTEMS_CHECK_RV( rv, "Read CRC 16");
490
491        return i;
492}
493
494static int sd_card_write( sd_card_driver_entry *e, uint8_t start_token, uint8_t *out, int n)
495{
496        int rv = 0;
497        uint8_t crc16 [2] = { 0, 0 };
498
499        /* Data output index */
500        int o = 0;
501
502        /* Wait until card is not busy */
503        rv = sd_card_wait( e);
504        RTEMS_CHECK_RV( rv, "Wait");
505
506        /* Write data start token */
507        rv = rtems_libi2c_write_bytes( e->bus, &start_token, 1);
508        RTEMS_CHECK_RV( rv, "Write data start token");
509
510        /* Write data */
511        o = rtems_libi2c_write_bytes( e->bus, out, n);
512        RTEMS_CHECK_RV( o, "Write data");
513
514        /* Write CRC 16 */
515        rv = rtems_libi2c_write_bytes( e->bus, crc16, 2);
516        RTEMS_CHECK_RV( rv, "Write CRC 16");
517
518        /* Read data response */
519        rv = sd_card_query( e, e->response, 2);
520        RTEMS_CHECK_RV( rv, "Read data response");
521        if (SD_CARD_IS_DATA_REJECTED( e->response [0])) {
522                RTEMS_SYSLOG_ERROR( "Data rejected: 0x%02" PRIx8 "\n", e->response [0]);
523                return -RTEMS_IO_ERROR;
524        }
525
526        /* Card is now busy */
527        e->busy = true;
528
529        return o;
530}
531
532static inline rtems_status_code sd_card_start( sd_card_driver_entry *e)
533{
534        rtems_status_code sc = RTEMS_SUCCESSFUL;
535        int rv = 0;
536
537        sc = rtems_libi2c_send_start( e->bus);
538        RTEMS_CHECK_SC( sc, "Send start");
539
540        rv = rtems_libi2c_ioctl( e->bus, RTEMS_LIBI2C_IOCTL_SET_TFRMODE, &e->transfer_mode);
541        RTEMS_CHECK_RV_SC( rv, "Set transfer mode");
542
543        sc = rtems_libi2c_send_addr( e->bus, 1);
544        RTEMS_CHECK_SC( sc, "Send address");
545
546        return RTEMS_SUCCESSFUL;
547}
548
549static inline rtems_status_code sd_card_stop( sd_card_driver_entry *e)
550{
551        rtems_status_code sc = RTEMS_SUCCESSFUL;
552
553        sc = rtems_libi2c_send_stop( e->bus);
554        RTEMS_CHECK_SC( sc, "Send stop");
555
556        return RTEMS_SUCCESSFUL;
557}
558
559static rtems_status_code sd_card_init( sd_card_driver_entry *e)
560{
561        rtems_status_code sc = RTEMS_SUCCESSFUL;
562        int rv = 0;
563        uint8_t block [SD_CARD_BLOCK_SIZE_DEFAULT];
564        uint32_t transfer_speed = 0;
565        uint32_t read_block_size = 0;
566        uint32_t write_block_size = 0;
567
568        /* Start */
569        sc = sd_card_start( e);
570        RTEMS_CLEANUP_SC( sc, sd_card_driver_init_cleanup, "Start");
571
572        /* Wait until card is not busy */
573        rv = sd_card_wait( e);
574        RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Wait");
575
576        /* Send idle tokens for at least 74 clock cycles with active chip select */
577        memset( block, SD_CARD_IDLE_TOKEN, SD_CARD_BLOCK_SIZE_DEFAULT);
578        rv = rtems_libi2c_write_bytes( e->bus, block, SD_CARD_BLOCK_SIZE_DEFAULT);
579        RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Active chip select delay");
580
581        /* Stop */
582        sc = sd_card_stop( e);
583        RTEMS_CHECK_SC( sc, "Stop");
584
585        /* Start with inactive chip select */
586        sc = rtems_libi2c_send_start( e->bus);
587        RTEMS_CHECK_SC( sc, "Send start");
588
589        /* Set transfer mode */
590        rv = rtems_libi2c_ioctl( e->bus, RTEMS_LIBI2C_IOCTL_SET_TFRMODE, &e->transfer_mode);
591        RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Set transfer mode");
592
593        /* Send idle tokens with inactive chip select */
594        rv = sd_card_query( e, e->response, SD_CARD_COMMAND_SIZE);
595        RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Inactive chip select delay");
596
597        /* Activate chip select */
598        sc = rtems_libi2c_send_addr( e->bus, 1);
599        RTEMS_CLEANUP_SC( sc, sd_card_driver_init_cleanup, "Send address");
600
601        /* Stop multiple block write */
602        sd_card_stop_multiple_block_write( e);
603
604        /* Get card status */
605        sd_card_send_command( e, SD_CARD_CMD_SEND_STATUS, 0);
606
607        /* Stop multiple block read */
608        sd_card_stop_multiple_block_read( e);
609
610        /* Switch to SPI mode */
611        rv = sd_card_send_command( e, SD_CARD_CMD_GO_IDLE_STATE, 0);
612        RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_GO_IDLE_STATE");
613
614        /* Initialize card */
615        while (true) {
616                rv = sd_card_send_command( e, SD_CARD_CMD_APP_CMD, 0);
617                RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_APP_CMD");
618                rv = sd_card_send_command( e, SD_CARD_ACMD_SD_SEND_OP_COND, 0);
619                RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_ACMD_SD_SEND_OP_COND");
620       
621                /* Not idle? */
622                if (SD_CARD_IS_NOT_IDLE_RESPONSE( e->response [e->response_index])) {
623                        break;
624                }
625
626                /* Invoke the scheduler */
627                rtems_task_wake_after( RTEMS_YIELD_PROCESSOR);
628        };
629
630        /* Card Identification */
631        if (e->verbose) {
632                rv = sd_card_send_command( e, SD_CARD_CMD_SEND_CID, 0);
633                RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_SEND_CID");
634                rv = sd_card_read( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_READ, block, SD_CARD_CID_SIZE);
635                RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Read: SD_CARD_CMD_SEND_CID");
636                RTEMS_SYSLOG( "*** Card Identification ***\n");
637                RTEMS_SYSLOG( "Manufacturer ID          : %" PRIu8 "\n", SD_CARD_CID_GET_MID( block));
638                RTEMS_SYSLOG( "OEM/Application ID       : %" PRIu16 "\n", SD_CARD_CID_GET_OID( block));
639                RTEMS_SYSLOG(
640                        "Product name             : %c%c%c%c%c%c\n",
641                        SD_CARD_CID_GET_PNM( block, 0),
642                        SD_CARD_CID_GET_PNM( block, 1),
643                        SD_CARD_CID_GET_PNM( block, 2),
644                        SD_CARD_CID_GET_PNM( block, 3),
645                        SD_CARD_CID_GET_PNM( block, 4),
646                        SD_CARD_CID_GET_PNM( block, 5)
647                );
648                RTEMS_SYSLOG( "Product revision         : %" PRIu8 "\n", SD_CARD_CID_GET_PRV( block));
649                RTEMS_SYSLOG( "Product serial number    : %" PRIu32 "\n", SD_CARD_CID_GET_PSN( block));
650                RTEMS_SYSLOG( "Manufacturing date       : %" PRIu8 "\n", SD_CARD_CID_GET_MDT( block));
651                RTEMS_SYSLOG( "7-bit CRC checksum       : %" PRIu8 "\n",  SD_CARD_CID_GET_CRC7( block));
652        }
653
654        /* Card Specific Data */
655        rv = sd_card_send_command( e, SD_CARD_CMD_SEND_CSD, 0);
656        RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_SEND_CSD");
657        rv = sd_card_read( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_READ, block, SD_CARD_CSD_SIZE);
658        RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Read: SD_CARD_CMD_SEND_CSD");
659        transfer_speed = sd_card_transfer_speed( block);
660        e->transfer_mode.baudrate = transfer_speed;
661        e->n_ac_max = sd_card_max_access_time( block, transfer_speed);
662        read_block_size = 1U << SD_CARD_CSD_GET_READ_BLK_LEN( block);
663        e->block_size_shift = SD_CARD_CSD_GET_READ_BLK_LEN( block);
664        write_block_size = 1U << e->block_size_shift;
665        if (read_block_size < write_block_size) {
666                RTEMS_SYSLOG_ERROR( "Read block size smaller than write block size\n");
667                return -RTEMS_IO_ERROR;
668        }
669        e->block_size = write_block_size;
670        e->block_number = sd_card_block_number( block);
671        if (e->verbose) {
672                RTEMS_SYSLOG( "*** Card Specific Data ***\n");
673                RTEMS_SYSLOG( "CSD structure            : %" PRIu8 "\n", SD_CARD_CSD_GET_CSD_STRUCTURE( block));
674                RTEMS_SYSLOG( "Spec version             : %" PRIu8 "\n", SD_CARD_CSD_GET_SPEC_VERS( block));
675                RTEMS_SYSLOG( "Access time [ns]         : %" PRIu32 "\n", sd_card_access_time( block));
676                RTEMS_SYSLOG( "Max access time [N]      : %" PRIu32 "\n", e->n_ac_max);
677                RTEMS_SYSLOG( "Max read block size [B]  : %" PRIu32 "\n", read_block_size);
678                RTEMS_SYSLOG( "Max write block size [B] : %" PRIu32 "\n", write_block_size);
679                RTEMS_SYSLOG( "Block size [B]           : %" PRIu32 "\n", e->block_size);
680                RTEMS_SYSLOG( "Block number             : %" PRIu32 "\n", e->block_number);
681                RTEMS_SYSLOG( "Capacity [B]             : %" PRIu32 "\n", sd_card_capacity( block));
682                RTEMS_SYSLOG( "Max transfer speed [b/s] : %" PRIu32 "\n", transfer_speed);
683        }
684
685        /* Set read block size */
686        rv = sd_card_send_command( e, SD_CARD_CMD_SET_BLOCKLEN, e->block_size);
687        RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_SET_BLOCKLEN");
688
689        /* Stop */
690        sc = sd_card_stop( e);
691        RTEMS_CHECK_SC( sc, "Stop");
692
693        return RTEMS_SUCCESSFUL;
694
695sd_card_driver_init_cleanup:
696
697        /* Stop */
698        sd_card_stop( e);
699
700        return sc;
701}
702/** @} */
703
704/**
705 * @name Disk Driver Functions
706 * @{
707 */
708
709static int sd_card_disk_block_read( sd_card_driver_entry *e, rtems_blkdev_request *r)
710{
711        rtems_status_code sc = RTEMS_SUCCESSFUL;
712        int rv = 0;
713        uint32_t start_address = RTEMS_BLKDEV_START_BLOCK (r) << e->block_size_shift;
714        uint32_t i = 0;
715
716#ifdef DEBUG
717        /* Check request */
718        if (r->bufs[0].block >= e->block_number) {
719                RTEMS_SYSLOG_ERROR( "Start block number out of range");
720                return -RTEMS_INTERNAL_ERROR;
721        } else if (r->bufnum > e->block_number - RTEMS_BLKDEV_START_BLOCK (r)) {
722                RTEMS_SYSLOG_ERROR( "Block count out of range");
723                return -RTEMS_INTERNAL_ERROR;
724        }
725#endif /* DEBUG */
726
727        /* Start */
728        sc = sd_card_start( e);
729        RTEMS_CLEANUP_SC_RV( sc, rv, sd_card_disk_block_read_cleanup, "Start");
730
731        if (r->bufnum == 1) {
732#ifdef DEBUG
733                /* Check buffer */
734                if (r->bufs [0].length != e->block_size) {
735                        RTEMS_DO_CLEANUP_RV( -RTEMS_INTERNAL_ERROR, rv, sd_card_disk_block_read_cleanup, "Buffer and disk block size are not equal");
736                }
737                RTEMS_DEBUG_PRINT( "[01:01]: buffer = 0x%08x, size = %u\n", r->bufs [0].buffer, r->bufs [0].length);
738#endif /* DEBUG */
739
740                /* Single block read */
741                rv = sd_card_send_command( e, SD_CARD_CMD_READ_SINGLE_BLOCK, start_address);
742                RTEMS_CLEANUP_RV( rv, sd_card_disk_block_read_cleanup, "Send: SD_CARD_CMD_READ_SINGLE_BLOCK");
743                rv = sd_card_read( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_READ, (uint8_t *) r->bufs [0].buffer, (int) e->block_size);
744                RTEMS_CLEANUP_RV( rv, sd_card_disk_block_read_cleanup, "Read: SD_CARD_CMD_READ_SINGLE_BLOCK");
745        } else {
746                /* Start multiple block read */
747                rv = sd_card_send_command( e, SD_CARD_CMD_READ_MULTIPLE_BLOCK, start_address);
748                RTEMS_CLEANUP_RV( rv, sd_card_disk_block_read_stop_cleanup, "Send: SD_CARD_CMD_READ_MULTIPLE_BLOCK");
749
750                /* Multiple block read */
751                for (i = 0; i < r->bufnum; ++i) {
752#ifdef DEBUG
753                        /* Check buffer */
754                        if (r->bufs [i].length != e->block_size) {
755                                RTEMS_DO_CLEANUP_RV( -RTEMS_INTERNAL_ERROR, rv, sd_card_disk_block_read_stop_cleanup, "Buffer and disk block size are not equal");
756                        }
757                        RTEMS_DEBUG_PRINT( "[%02u:%02u]: buffer = 0x%08x, size = %u\n", i + 1, r->bufnum, r->bufs [i].buffer, r->bufs [i].length);
758#endif /* DEBUG */
759
760                        rv = sd_card_read( e, SD_CARD_START_BLOCK_MULTIPLE_BLOCK_READ, (uint8_t *) r->bufs [i].buffer, (int) e->block_size);
761                        RTEMS_CLEANUP_RV( rv, sd_card_disk_block_read_stop_cleanup, "Read block");
762                }
763
764                /* Stop multiple block read */
765                rv = sd_card_stop_multiple_block_read( e);
766                RTEMS_CLEANUP_RV( rv, sd_card_disk_block_read_cleanup, "Stop multiple block read");
767        }
768
769        /* Stop */
770        sc = sd_card_stop( e);
771        RTEMS_CHECK_SC_RV( sc, "Stop");
772
773        /* Done */
774        r->req_done( r->done_arg, RTEMS_SUCCESSFUL, 0);
775
776        return 0;
777
778sd_card_disk_block_read_stop_cleanup:
779
780        /* Stop multiple block read */
781        sd_card_stop_multiple_block_read( e);
782
783sd_card_disk_block_read_cleanup:
784
785        /* Stop */
786        sd_card_stop( e);
787
788        /* Done */
789        r->req_done( r->done_arg, RTEMS_IO_ERROR, 0);
790
791        return rv;
792}
793
794static int sd_card_disk_block_write( sd_card_driver_entry *e, rtems_blkdev_request *r)
795{
796        rtems_status_code sc = RTEMS_SUCCESSFUL;
797        int rv = 0;
798        uint32_t start_address = RTEMS_BLKDEV_START_BLOCK (r) << e->block_size_shift;
799        uint32_t i = 0;
800
801#ifdef DEBUG
802        /* Check request */
803        if (r->bufs[0].block >= e->block_number) {
804                RTEMS_SYSLOG_ERROR( "Start block number out of range");
805                return -RTEMS_INTERNAL_ERROR;
806        } else if (r->bufnum > e->block_number - RTEMS_BLKDEV_START_BLOCK (r)) {
807                RTEMS_SYSLOG_ERROR( "Block count out of range");
808                return -RTEMS_INTERNAL_ERROR;
809        }
810#endif /* DEBUG */
811
812        /* Start */
813        sc = sd_card_start( e);
814        RTEMS_CLEANUP_SC_RV( sc, rv, sd_card_disk_block_write_cleanup, "Start");
815
816        if (r->bufnum == 1) {
817#ifdef DEBUG
818                /* Check buffer */
819                if (r->bufs [0].length != e->block_size) {
820                        RTEMS_DO_CLEANUP_RV( -RTEMS_INTERNAL_ERROR, rv, sd_card_disk_block_write_cleanup, "Buffer and disk block size are not equal");
821                }
822                RTEMS_DEBUG_PRINT( "[01:01]: buffer = 0x%08x, size = %u\n", r->bufs [0].buffer, r->bufs [0].length);
823#endif /* DEBUG */
824
825                /* Single block write */
826                rv = sd_card_send_command( e, SD_CARD_CMD_WRITE_BLOCK, start_address);
827                RTEMS_CLEANUP_RV( rv, sd_card_disk_block_write_cleanup, "Send: SD_CARD_CMD_WRITE_BLOCK");
828                rv = sd_card_write( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_WRITE, (uint8_t *) r->bufs [0].buffer, (int) e->block_size);
829                RTEMS_CLEANUP_RV( rv, sd_card_disk_block_write_cleanup, "Write: SD_CARD_CMD_WRITE_BLOCK");
830        } else {
831                /* Start multiple block write */
832                rv = sd_card_send_command( e, SD_CARD_CMD_WRITE_MULTIPLE_BLOCK, start_address);
833                RTEMS_CLEANUP_RV( rv, sd_card_disk_block_write_stop_cleanup, "Send: SD_CARD_CMD_WRITE_MULTIPLE_BLOCK");
834
835                /* Multiple block write */
836                for (i = 0; i < r->bufnum; ++i) {
837#ifdef DEBUG
838                        /* Check buffer */
839                        if (r->bufs [i].length != e->block_size) {
840                                RTEMS_DO_CLEANUP_RV( -RTEMS_INTERNAL_ERROR, rv, sd_card_disk_block_write_stop_cleanup, "Buffer and disk block size are not equal");
841                        }
842                        RTEMS_DEBUG_PRINT( "[%02u:%02u]: buffer = 0x%08x, size = %u\n", i + 1, r->bufnum, r->bufs [i].buffer, r->bufs [i].length);
843#endif /* DEBUG */
844
845                        rv = sd_card_write( e, SD_CARD_START_BLOCK_MULTIPLE_BLOCK_WRITE, (uint8_t *) r->bufs [i].buffer, (int) e->block_size);
846                        RTEMS_CLEANUP_RV( rv, sd_card_disk_block_write_stop_cleanup, "Write block");
847                }
848
849                /* Stop multiple block write */
850                rv = sd_card_stop_multiple_block_write( e);
851                RTEMS_CLEANUP_RV( rv, sd_card_disk_block_write_cleanup, "Stop multiple block write");
852        }
853
854        /* Get card status */
855        rv = sd_card_send_command( e, SD_CARD_CMD_SEND_STATUS, 0);
856        RTEMS_CHECK_RV( rv, "Send: SD_CARD_CMD_SEND_STATUS");
857
858        /* Stop */
859        sc = sd_card_stop( e);
860        RTEMS_CHECK_SC_RV( sc, "Stop");
861
862        /* Done */
863        r->req_done( r->done_arg, RTEMS_SUCCESSFUL, 0);
864
865        return 0;
866
867sd_card_disk_block_write_stop_cleanup:
868
869        /* Stop multiple block write */
870        sd_card_stop_multiple_block_write( e);
871
872sd_card_disk_block_write_cleanup:
873
874        /* Get card status */
875        rv = sd_card_send_command( e, SD_CARD_CMD_SEND_STATUS, 0);
876        RTEMS_CHECK_RV( rv, "Send: SD_CARD_CMD_SEND_STATUS");
877
878        /* Stop */
879        sd_card_stop( e);
880
881        /* Done */
882        r->req_done( r->done_arg, RTEMS_IO_ERROR, 0);
883
884        return rv;
885}
886
887static int sd_card_disk_ioctl( dev_t dev, uint32_t req, void *arg)
888{
889        RTEMS_DEBUG_PRINT( "dev = %u, req = %u, arg = 0x08%x\n", dev, req, arg);
890        if (req == RTEMS_BLKIO_REQUEST) {
891                rtems_device_minor_number minor = rtems_filesystem_dev_minor_t( dev);
892                sd_card_driver_entry *e = &sd_card_driver_table [minor];
893                rtems_blkdev_request *r = (rtems_blkdev_request *) arg;
894                switch (r->req) {
895                        case RTEMS_BLKDEV_REQ_READ:
896                                return sd_card_disk_block_read( e, r);
897                        case RTEMS_BLKDEV_REQ_WRITE:
898                                return sd_card_disk_block_write( e, r);
899                        default:
900                                errno = EBADRQC;
901                                return -1;
902                }
903        } else if (req == RTEMS_BLKDEV_CAPABILITIES) {
904                *(uint32_t*) arg = RTEMS_BLKDEV_CAP_MULTISECTOR_CONT;
905                return 0;
906        } else {
907                errno = EBADRQC;
908                return -1;
909        }
910}
911
912static rtems_status_code sd_card_disk_init( rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
913{
914        rtems_status_code sc = RTEMS_SUCCESSFUL;
915        sd_card_driver_entry *e = NULL;
916        dev_t dev = 0;
917
918        /* Initialize disk IO */
919        sc = rtems_disk_io_initialize();
920        RTEMS_CHECK_SC( sc, "Initialize RTEMS disk IO");
921
922        for (minor = 0; minor < sd_card_driver_table_size; ++minor) {
923                e = &sd_card_driver_table [minor];
924
925                /* Initialize SD Card */
926                sc = sd_card_init( e);
927                RTEMS_CHECK_SC( sc, "Initialize SD Card");
928
929                /* Create disk device */
930                dev = rtems_filesystem_make_dev_t( major, minor);
931                sc = rtems_disk_create_phys( dev, (int) e->block_size, (int) e->block_number, sd_card_disk_ioctl, e->device_name);
932                RTEMS_CHECK_SC( sc, "Create disk device");
933        }
934
935        return RTEMS_SUCCESSFUL;
936}
937
938/** @} */
939
940static const rtems_driver_address_table sd_card_disk_ops = {
941        .initialization_entry = sd_card_disk_init,
942        .open_entry = rtems_blkdev_generic_open,
943        .close_entry = rtems_blkdev_generic_close,
944        .read_entry = rtems_blkdev_generic_read,
945        .write_entry = rtems_blkdev_generic_write,
946        .control_entry = rtems_blkdev_generic_ioctl
947};
948
949rtems_status_code sd_card_register( void)
950{
951        rtems_status_code sc = RTEMS_SUCCESSFUL;
952        rtems_device_major_number major = 0;
953
954        sc = rtems_io_register_driver( 0, &sd_card_disk_ops, &major);
955        RTEMS_CHECK_SC( sc, "Register disk SD Card driver");
956
957        return RTEMS_SUCCESSFUL;
958}
Note: See TracBrowser for help on using the repository browser.