aboutsummaryrefslogtreecommitdiff
path: root/include/linux/sdio/_sdio_defs.h
blob: a3f5542061c11665134ca9d82709065fb3b28916 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@file: _sdio_defs.h

@abstract: SD/SDIO definitions

@notice: Copyright (c), 2004-2006 Atheros Communications, Inc.


 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation;
 *
 *  Software distributed under the License is distributed on an "AS
 *  IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 *  implied. See the License for the specific language governing
 *  rights and limitations under the License.
 *
 *  Portions of this code were developed with information supplied from the
 *  SD Card Association Simplified Specifications. The following conditions and disclaimers may apply:
 *
 *   The following conditions apply to the release of the SD simplified specification (�Simplified
 *   Specification�) by the SD Card Association. The Simplified Specification is a subset of the complete
 *   SD Specification which is owned by the SD Card Association. This Simplified Specification is provided
 *   on a non-confidential basis subject to the disclaimers below. Any implementation of the Simplified
 *   Specification may require a license from the SD Card Association or other third parties.
 *   Disclaimers:
 *   The information contained in the Simplified Specification is presented only as a standard
 *   specification for SD Cards and SD Host/Ancillary products and is provided "AS-IS" without any
 *   representations or warranties of any kind. No responsibility is assumed by the SD Card Association for
 *   any damages, any infringements of patents or other right of the SD Card Association or any third
 *   parties, which may result from its use. No license is granted by implication, estoppel or otherwise
 *   under any patent or other rights of the SD Card Association or any third party. Nothing herein shall
 *   be construed as an obligation by the SD Card Association to disclose or distribute any technical
 *   information, know-how or other confidential information to any third party.
 *
 *
 *  The initial developers of the original code are Seung Yi and Paul Lever
 *
 *  sdio@atheros.com
 *
 *

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#ifndef ___SDIO_DEFS_H___
#define ___SDIO_DEFS_H___

#define SD_INIT_BUS_CLOCK   100000    /* initialization clock in hz */
#define SPI_INIT_BUS_CLOCK  100000    /* initialization clock in hz */
#define SD_MAX_BUS_CLOCK    25000000  /* max clock speed in hz */
#define SD_HS_MAX_BUS_CLOCK 50000000  /* SD high speed max clock speed in hz */
#define SDIO_LOW_SPEED_MAX_BUS_CLOCK 400000 /* max low speed clock in hz */
#define SDMMC_MIN_INIT_CLOCKS   80    /* minimun number of initialization clocks */
#define SDIO_EMPC_CURRENT_THRESHOLD  300  /* SDIO 1.10 , EMPC (mA) threshold, we add some overhead */

/* commands */
#define CMD0    0
#define CMD1    1
#define CMD2    2
#define CMD3    3
#define CMD4    4
#define CMD5    5
#define CMD6    6
#define CMD7    7
#define CMD9    9
#define CMD10   10
#define CMD12   12
#define CMD13   13
#define CMD15   15
#define CMD16   16
#define CMD17   17
#define CMD18   18
#define CMD24   24
#define CMD25   25
#define CMD27   27
#define CMD28   28
#define CMD29   29
#define CMD30   30
#define CMD32   32
#define CMD33   33
#define CMD38   38
#define CMD42   42
#define CMD52   52
#define CMD53   53
#define CMD55   55
#define CMD56   56
#define CMD58   58
#define CMD59   59
#define ACMD6   6
#define ACMD13  13
#define ACMD22  22
#define ACMD23  23
#define ACMD41  41
#define ACMD42  42
#define ACMD51  51

#define SD_ACMD6_BUS_WIDTH_1_BIT         0x00
#define SD_ACMD6_BUS_WIDTH_4_BIT         0x02

#define SD_CMD59_CRC_OFF            0x00000000
#define SD_CMD59_CRC_ON             0x00000001

/* SD/SPI max response size */
#define SD_MAX_CMD_RESPONSE_BYTES SD_R2_RESPONSE_BYTES

#define SD_R1_RESPONSE_BYTES  6
#define SD_R1B_RESPONSE_BYTES SD_R1_RESPONSE_BYTES
#define SD_R1_GET_CMD(pR) ((pR)[5] & 0xC0))
#define SD_R1_SET_CMD(pR,cmd)  (pR)[5] = (cmd) & 0xC0
#define SD_R1_GET_CARD_STATUS(pR) (((UINT32)((pR)[1]))        |  \
                                  (((UINT32)((pR)[2])) << 8)  |  \
                                  (((UINT32)((pR)[3])) << 16) |  \
                                  (((UINT32)((pR)[4])) << 24) )
#define SD_R1_SET_CMD_STATUS(pR,status) \
{                                      \
    (pR)[1] = (UINT8)(status);         \
    (pR)[2] = (UINT8)((status) >> 8);  \
    (pR)[3] = (UINT8)((status) >> 16); \
    (pR)[4] = (UINT8)((status) >> 24); \
}

/* SD R1 card status bit masks */
#define SD_CS_CMD_OUT_OF_RANGE  ((UINT32)(1 << 31))
#define SD_CS_ADDRESS_ERR       (1 << 30)
#define SD_CS_BLK_LEN_ERR       (1 << 29)
#define SD_CS_ERASE_SEQ_ERR     (1 << 28)
#define SD_CS_ERASE_PARAM_ERR   (1 << 27)
#define SD_CS_WP_ERR            (1 << 26)
#define SD_CS_CARD_LOCKED       (1 << 25)
#define SD_CS_LK_UNLK_FAILED    (1 << 24)
#define SD_CS_PREV_CMD_CRC_ERR  (1 << 23)
#define SD_CS_ILLEGAL_CMD_ERR   (1 << 22)
#define SD_CS_ECC_FAILED        (1 << 21)
#define SD_CS_CARD_INTERNAL_ERR (1 << 20)
#define SD_CS_GENERAL_ERR       (1 << 19)
#define SD_CS_CSD_OVERWR_ERR    (1 << 16)
#define SD_CS_WP_ERASE_SKIP     (1 << 15)
#define SD_CS_ECC_DISABLED      (1 << 14)
#define SD_CS_ERASE_RESET       (1 << 13)
#define SD_CS_GET_STATE(status) (((status) >> 9) & 0x0f)
#define SD_CS_SET_STATE(status, state) \
{                               \
    (status) &= ~(0x0F << 9);   \
    (status) |= (state) << 9    \
}

#define SD_CS_TRANSFER_ERRORS \
                ( SD_CS_ADDRESS_ERR       | \
                  SD_CS_BLK_LEN_ERR       | \
                  SD_CS_ERASE_SEQ_ERR     | \
                  SD_CS_ERASE_PARAM_ERR   | \
                  SD_CS_WP_ERR            | \
                  SD_CS_ECC_FAILED        | \
                  SD_CS_CARD_INTERNAL_ERR | \
                  SD_CS_GENERAL_ERR )

#define SD_CS_STATE_IDLE   0
#define SD_CS_STATE_READY  1
#define SD_CS_STATE_IDENT  2
#define SD_CS_STATE_STBY   3
#define SD_CS_STATE_TRANS  4
#define SD_CS_STATE_DATA   5
#define SD_CS_STATE_RCV    6
#define SD_CS_STATE_PRG    7
#define SD_CS_STATE_DIS    8
#define SD_CS_READY_FOR_DATA    (1 << 8)
#define SD_CS_APP_CMD           (1 << 5)
#define SD_CS_AKE_SEQ_ERR       (1 << 3)

/* SD R2 response */
#define SD_R2_RESPONSE_BYTES  17
#define MAX_CSD_CID_BYTES     16
#define SD_R2_SET_STUFF_BITS(pR)   (pR)[16] = 0x3F
#define GET_SD_CSD_TRANS_SPEED(pR) (pR)[12]
#define GET_SD_CID_MANFID(pR)      (pR)[15]
#define GET_SD_CID_PN_1(pR)        (pR)[12]
#define GET_SD_CID_PN_2(pR)        (pR)[11]
#define GET_SD_CID_PN_3(pR)        (pR)[10]
#define GET_SD_CID_PN_4(pR)        (pR)[9]
#define GET_SD_CID_PN_5(pR)        (pR)[8]
#define GET_SD_CID_PN_6(pR)        (pR)[7]

#define GET_SD_CID_OEMID(pR)      ((((UINT16)(pR)[14]) << 8 )| (UINT16)((pR)[13]))
#define SDMMC_OCR_VOLTAGE_MASK 0x7FFFFFFF
/* SD R3 response */
#define SD_R3_RESPONSE_BYTES 6
#define SD_R3_GET_OCR(pR) ((((UINT32)((pR)[1])) |  \
                           (((UINT32)((pR)[2])) << 8)  |  \
                           (((UINT32)((pR)[3])) << 16) | \
                           (((UINT32)((pR)[4])) << 24)) & SDMMC_OCR_VOLTAGE_MASK)
#define SD_R3_IS_CARD_READY(pR)  (((pR)[4] & 0x80) == 0x80)

/* OCR bit definitions */
#define SD_OCR_CARD_PWR_UP_STATUS  ((UINT32)(1 << 31))
#define SD_OCR_3_5_TO_3_6_VDD      (1 << 23)
#define SD_OCR_3_4_TO_3_5_VDD      (1 << 22)
#define SD_OCR_3_3_TO_3_4_VDD      (1 << 21)
#define SD_OCR_3_2_TO_3_3_VDD      (1 << 20)
#define SD_OCR_3_1_TO_3_2_VDD      (1 << 19)
#define SD_OCR_3_0_TO_3_1_VDD      (1 << 18)
#define SD_OCR_2_9_TO_3_0_VDD      (1 << 17)
#define SD_OCR_2_8_TO_2_9_VDD      (1 << 16)
#define SD_OCR_2_7_TO_2_8_VDD      (1 << 15)
#define SD_OCR_2_6_TO_2_7_VDD      (1 << 14)
#define SD_OCR_2_5_TO_2_6_VDD      (1 << 13)
#define SD_OCR_2_4_TO_2_5_VDD      (1 << 12)
#define SD_OCR_2_3_TO_2_4_VDD      (1 << 11)
#define SD_OCR_2_2_TO_2_3_VDD      (1 << 10)
#define SD_OCR_2_1_TO_2_2_VDD      (1 << 9)
#define SD_OCR_2_0_TO_2_1_VDD      (1 << 8)
#define SD_OCR_1_9_TO_2_0_VDD      (1 << 7)
#define SD_OCR_1_8_TO_1_9_VDD      (1 << 6)
#define SD_OCR_1_7_TO_1_8_VDD      (1 << 5)
#define SD_OCR_1_6_TO_1_7_VDD      (1 << 4)

/* SD Status data block */
#define SD_STATUS_DATA_BYTES        64
#define SDS_GET_DATA_WIDTH(buffer)  ((buffer)[0] & 0xC0)
#define SDS_BUS_1_BIT               0x00
#define SDS_BUS_4_BIT               0x80
#define SDS_GET_SECURE_MODE(buffer) ((buffer)[0] & 0x20)
#define SDS_CARD_SECURE_MODE        0x20
#define SDS_GET_CARD_TYPE(buffer)   ((buffer)[60] & 0x0F)
#define SDS_SD_CARD_RW              0x00
#define SDS_SD_CARD_ROM             0x01

/* SD R6 response */
#define SD_R6_RESPONSE_BYTES 6
#define SD_R6_GET_RCA(pR) ((UINT16)((pR)[3]) | (((UINT16)((pR)[4])) << 8))
#define SD_R6_GET_CS(pR)  ((UINT16)((pR)[1]) | (((UINT16)((pR)[2])) << 8))

/* SD Configuration Register (SCR) */
#define SD_SCR_BYTES            8
#define SCR_REV_1_0             0x00
#define SCR_SD_SPEC_1_00        0x00
#define SCR_SD_SPEC_1_10        0x01
#define SCR_BUS_SUPPORTS_1_BIT  0x01
#define SCR_BUS_SUPPORTS_4_BIT  0x04
#define SCR_SD_SECURITY_MASK    0x70
#define SCR_SD_NO_SECURITY      0x00
#define SCR_SD_SECURITY_1_0     0x10
#define SCR_SD_SECURITY_2_0     0x20
#define SCR_DATA_STATUS_1_AFTER_ERASE  0x80

#define GET_SD_SCR_STRUCT_VER(pB) ((pB)[7] >> 4)
#define GET_SD_SCR_SDSPEC_VER(pB) ((pB)[7] & 0x0F)
#define GET_SD_SCR_BUSWIDTHS(pB)  ((pB)[6] & 0x0F)
#define GET_SD_SCR_BUSWIDTHS_FLAGS(pB)  (pB)[6]
#define GET_SD_SCR_SECURITY(pB)   (((pB)[6] >> 4) & 0x07)
#define GET_SD_SCR_DATA_STAT_AFTER_ERASE(pB) (((pB)[6] >> 7) & 0x01)

/* SDIO R4 Response */
#define SD_SDIO_R4_RESPONSE_BYTES 6
#define SD_SDIO_R4_GET_OCR(pR) ((UINT32)((pR)[1])        |  \
                          (((UINT32)(pR)[2]) << 8)  |  \
                          (((UINT32)(pR)[3]) << 16))
#define SD_SDIO_R4_IS_MEMORY_PRESENT(pR)   (((pR)[4] & 0x08) == 0x08)
#define SD_SDIO_R4_GET_IO_FUNC_COUNT(pR)   (((pR)[4] >> 4) & 0x07)
#define SD_SDIO_R4_IS_CARD_READY(pR)       (((pR)[4] & 0x80) == 0x80)

/* SDIO R5 response */
#define SD_SDIO_R5_RESPONSE_BYTES      6
#define SD_SDIO_R5_READ_DATA_OFFSET    1
#define SD_R5_GET_READ_DATA(pR)  (pR)[SD_SDIO_R5_READ_DATA_OFFSET]
#define SD_R5_RESP_FLAGS_OFFSET   2
#define SD_R5_GET_RESP_FLAGS(pR) (pR)[SD_R5_RESP_FLAGS_OFFSET]
#define SD_R5_SET_CMD(pR,cmd)  (pR)[5] = (cmd) & 0xC0
#define SD_R5_RESP_CMD_ERR  (1 << 7) /* for previous cmd */
#define SD_R5_ILLEGAL_CMD   (1 << 6)
#define SD_R5_GENERAL_ERR   (1 << 3)
#define SD_R5_INVALID_FUNC  (1 << 1)
#define SD_R5_ARG_RANGE_ERR (1 << 0)
#define SD_R5_CURRENT_CMD_ERRORS (SD_R5_ILLEGAL_CMD | SD_R5_GENERAL_ERR \
                                 | SD_R5_INVALID_FUNC | SD_R5_ARG_RANGE_ERR)
#define SD_R5_ERRORS (SD_R5_CURRENT_CMD_ERRORS)

#define SD_R5_GET_IO_STATE(pR) (((pR)[2] >> 4) & 0x03)
#define SD_R5_STATE_DIS 0x00
#define SD_R5_STATE_CMD 0x01
#define SD_R5_STATE_TRN 0x02

/* SDIO Modified R6 Response */
#define SD_SDIO_R6_RESPONSE_BYTES 6
#define SD_SDIO_R6_GET_RCA(pR)  ((UINT16)((pR)[3]) | ((UINT16)((pR)[4]) << 8))
#define SD_SDIO_R6_GET_CSTAT(pR)((UINT16)((pR)[1]) | ((UINT16)((pR)[2]) << 8))

/* SPI mode R1 response */
#define SPI_R1_RESPONSE_BYTES   1
#define GET_SPI_R1_RESP_TOKEN(pR) (pR)[0]
#define SPI_CS_STATE_IDLE       0x01
#define SPI_CS_ERASE_RESET      (1 << 1)
#define SPI_CS_ILLEGAL_CMD      (1 << 2)
#define SPI_CS_CMD_CRC_ERR      (1 << 3)
#define SPI_CS_ERASE_SEQ_ERR    (1 << 4)
#define SPI_CS_ADDRESS_ERR      (1 << 5)
#define SPI_CS_PARAM_ERR        (1 << 6)
#define SPI_CS_ERR_MASK         0x7c

/* SPI mode R2 response */
#define SPI_R2_RESPONSE_BYTES  2
#define GET_SPI_R2_RESP_TOKEN(pR)   (pR)[1]
#define GET_SPI_R2_STATUS_TOKEN(pR) (pR)[0]
/* the first response byte is defined above */
/* the second response byte is defined below */
#define SPI_CS_CARD_IS_LOCKED      (1 << 0)
#define SPI_CS_LOCK_UNLOCK_FAILED  (1 << 1)
#define SPI_CS_ERROR               (1 << 2)
#define SPI_CS_INTERNAL_ERROR      (1 << 3)
#define SPI_CS_ECC_FAILED          (1 << 4)
#define SPI_CS_WP_VIOLATION        (1 << 5)
#define SPI_CS_ERASE_PARAM_ERR     (1 << 6)
#define SPI_CS_OUT_OF_RANGE        (1 << 7)

/* SPI mode R3 response */
#define SPI_R3_RESPONSE_BYTES 5
#define SPI_R3_GET_OCR(pR) ((((UINT32)((pR)[0])) |         \
                            (((UINT32)((pR)[1])) << 8)  |  \
                            (((UINT32)((pR)[2])) << 16) |  \
                            (((UINT32)((pR)[3])) << 24)) & SDMMC_OCR_VOLTAGE_MASK)
#define SPI_R3_IS_CARD_READY(pR)  (((pR)[3] & 0x80) == 0x80)
#define GET_SPI_R3_RESP_TOKEN(pR) (pR)[4]

/* SPI mode SDIO R4 response */
#define SPI_SDIO_R4_RESPONSE_BYTES 5
#define SPI_SDIO_R4_GET_OCR(pR) ((UINT32)((pR)[0])        |  \
                          (((UINT32)(pR)[1]) << 8)   |  \
                          (((UINT32)(pR)[2]) << 16))
#define SPI_SDIO_R4_IS_MEMORY_PRESENT(pR)   (((pR)[3] & 0x08) == 0x08)
#define SPI_SDIO_R4_GET_IO_FUNC_COUNT(pR)   (((pR)[3] >> 4) & 0x07)
#define SPI_SDIO_R4_IS_CARD_READY(pR)       (((pR)[3] & 0x80) == 0x80)
#define GET_SPI_SDIO_R4_RESP_TOKEN(pR)  (pR)[4]

/* SPI Mode SDIO R5 response */
#define SPI_SDIO_R5_RESPONSE_BYTES 2
#define GET_SPI_SDIO_R5_RESP_TOKEN(pR)     (pR)[1]
#define GET_SPI_SDIO_R5_RESPONSE_RDATA(pR) (pR)[0]
#define SPI_R5_IDLE_STATE   0x01
#define SPI_R5_ILLEGAL_CMD  (1 << 2)
#define SPI_R5_CMD_CRC      (1 << 3)
#define SPI_R5_FUNC_ERR     (1 << 4)
#define SPI_R5_PARAM_ERR    (1 << 6)

/* SDIO COMMAND 52 Definitions */
#define CMD52_READ  0
#define CMD52_WRITE 1
#define CMD52_READ_AFTER_WRITE 1
#define CMD52_NORMAL_WRITE     0
#define SDIO_SET_CMD52_ARG(arg,rw,func,raw,address,writedata) \
    (arg) = (((rw) & 1) << 31)           | \
            (((func) & 0x7) << 28)       | \
            (((raw) & 1) << 27)          | \
            (1 << 26)                    | \
            (((address) & 0x1FFFF) << 9) | \
            (1 << 8)                     | \
            ((writedata) & 0xFF)
#define SDIO_SET_CMD52_READ_ARG(arg,func,address) \
    SDIO_SET_CMD52_ARG(arg,CMD52_READ,(func),0,address,0x00)
#define SDIO_SET_CMD52_WRITE_ARG(arg,func,address,value) \
    SDIO_SET_CMD52_ARG(arg,CMD52_WRITE,(func),CMD52_NORMAL_WRITE,address,value)

/* SDIO COMMAND 53 Definitions */
#define CMD53_READ          0
#define CMD53_WRITE         1
#define CMD53_BLOCK_BASIS   1
#define CMD53_BYTE_BASIS    0
#define CMD53_FIXED_ADDRESS 0
#define CMD53_INCR_ADDRESS  1
#define SDIO_SET_CMD53_ARG(arg,rw,func,mode,opcode,address,bytes_blocks) \
    (arg) = (((rw) & 1) << 31)                  | \
            (((func) & 0x7) << 28)              | \
            (((mode) & 1) << 27)                | \
            (((opcode) & 1) << 26)              | \
            (((address) & 0x1FFFF) << 9)        | \
            ((bytes_blocks) & 0x1FF)

#define SDIO_MAX_LENGTH_BYTE_BASIS  512
#define SDIO_MAX_BLOCKS_BLOCK_BASIS 511
#define SDIO_MAX_BYTES_PER_BLOCK    2048
#define SDIO_COMMON_AREA_FUNCTION_NUMBER 0
#define SDIO_FIRST_FUNCTION_NUMBER       1
#define SDIO_LAST_FUNCTION_NUMBER        7

#define CMD53_CONVERT_BYTE_BASIS_BLK_LENGTH_PARAM(b) (((b) < SDIO_MAX_LENGTH_BYTE_BASIS) ? (b) : 0)
#define CMD53_CONVERT_BLOCK_BASIS_BLK_COUNT_PARAM(b) (((b) <= SDIO_MAX_BLOCKS_BLOCK_BASIS) ? (b) : 0)


/* SDIO COMMON Registers */

/* revision register */
#define CCCR_SDIO_REVISION_REG  0x00
#define CCCR_REV_MASK           0x0F
#define CCCR_REV_1_0            0x00
#define CCCR_REV_1_1            0x01
#define SDIO_REV_MASK           0xF0
#define SDIO_REV_1_00           0x00
#define SDIO_REV_1_10           0x10
#define SDIO_REV_1_20           0x20
/* SD physical spec revision */
#define SD_SPEC_REVISION_REG    0x01
#define SD_REV_MASK             0x0F
#define SD_REV_1_01             0x00
#define SD_REV_1_10             0x01
/* I/O Enable  */
#define SDIO_ENABLE_REG         0x02
/* I/O Ready */
#define SDIO_READY_REG          0x03
/* Interrupt Enable */
#define SDIO_INT_ENABLE_REG     0x04
#define SDIO_INT_MASTER_ENABLE  0x01
#define SDIO_INT_ALL_ENABLE     0xFE
/* Interrupt Pending */
#define SDIO_INT_PENDING_REG    0x05
#define SDIO_INT_PEND_MASK      0xFE
/* I/O Abort */
#define SDIO_IO_ABORT_REG       0x06
#define SDIO_IO_RESET           (1 << 3)
/* Bus Interface */
#define SDIO_BUS_IF_REG         0x07
#define CARD_DETECT_DISABLE     0x80
#define SDIO_BUS_WIDTH_1_BIT    0x00
#define SDIO_BUS_WIDTH_4_BIT    0x02
/* Card Capabilities */
#define SDIO_CARD_CAPS_REG          0x08
#define SDIO_CAPS_CMD52_WHILE_DATA  0x01   /* card can issue CMD52 while data transfer */
#define SDIO_CAPS_MULTI_BLOCK       0x02   /* card supports multi-block data transfers */
#define SDIO_CAPS_READ_WAIT         0x04   /* card supports read-wait protocol */
#define SDIO_CAPS_SUSPEND_RESUME    0x08   /* card supports I/O function suspend/resume */
#define SDIO_CAPS_INT_MULTI_BLK     0x10   /* interrupts between multi-block data capable */
#define SDIO_CAPS_ENB_INT_MULTI_BLK 0x20   /* enable ints between muli-block data */
#define SDIO_CAPS_LOW_SPEED         0x40   /* low speed card */
#define SDIO_CAPS_4BIT_LS           0x80   /* 4 bit low speed card */
/* Common CIS pointer */
#define SDIO_CMN_CIS_PTR_LOW_REG    0x09
#define SDIO_CMN_CIS_PTR_MID_REG    0x0a
#define SDIO_CMN_CIS_PTR_HI_REG     0x0b
/* Bus suspend */
#define SDIO_BUS_SUSPEND_REG            0x0c
#define SDIO_FUNC_SUSPEND_STATUS_MASK   0x01 /* selected function is suspended */
#define SDIO_SUSPEND_FUNCTION           0x02 /* suspend the current selected function */
/* Function select (for bus suspension) */
#define SDIO_FUNCTION_SELECT_REG        0x0d
#define SDIO_SUSPEND_FUNCTION_0         0x00
#define SDIO_SUSPEND_MEMORY_FUNC_MASK    0x08
/* Function Execution */
#define SDIO_FUNCTION_EXEC_REG          0x0e
#define SDIO_MEMORY_FUNC_EXEC_MASK      0x01
/* Function Ready */
#define SDIO_FUNCTION_READY_REG          0x0f
#define SDIO_MEMORY_FUNC_BUSY_MASK       0x01

/* power control 1.10 only  */
#define SDIO_POWER_CONTROL_REG            0x12
#define SDIO_POWER_CONTROL_SMPC           0x01
#define SDIO_POWER_CONTROL_EMPC           0x02

/* high speed control , 1.20 only */
#define SDIO_HS_CONTROL_REG               0x13
#define SDIO_HS_CONTROL_SHS               0x01
#define SDIO_HS_CONTROL_EHS               0x02

/* Function Base Registers */
#define xFUNCTION_FBR_OFFSET(funcNo) (0x100*(funcNo))
/* offset calculation that does not use multiplication */
static INLINE UINT32 CalculateFBROffset(UCHAR FuncNo) {
    UCHAR i = FuncNo;
    UINT32 offset = 0;
    while (i) {
        offset += 0x100;
        i--;
    }
    return offset;
}
/* Function info */
#define FBR_FUNC_INFO_REG_OFFSET(fbr)   ((fbr) + 0x00)
#define FUNC_INFO_SUPPORTS_CSA_MASK     0x40
#define FUNC_INFO_ENABLE_CSA            0x80
#define FUNC_INFO_DEVICE_CODE_MASK      0x0F
#define FUNC_INFO_DEVICE_CODE_LAST      0x0F
#define FBR_FUNC_EXT_DEVICE_CODE_OFFSET(fbr) ((fbr) + 0x01)
/* Function Power selection */
#define FBR_FUNC_POWER_SELECT_OFFSET(fbr)    ((fbr) + 0x02)
#define FUNC_POWER_SELECT_SPS           0x01
#define FUNC_POWER_SELECT_EPS           0x02
/* Function CIS ptr */
#define FBR_FUNC_CIS_LOW_OFFSET(fbr)   ((fbr) + 0x09)
#define FBR_FUNC_CIS_MID_OFFSET(fbr)   ((fbr) + 0x0a)
#define FBR_FUNC_CIS_HI_OFFSET(fbr)    ((fbr) + 0x0b)
/* Function CSA ptr */
#define FBR_FUNC_CSA_LOW_OFFSET(fbr)   ((fbr) + 0x0c)
#define FBR_FUNC_CSA_MID_OFFSET(fbr)   ((fbr) + 0x0d)
#define FBR_FUNC_CSA_HI_OFFSET(fbr)    ((fbr) + 0x0e)
/* Function CSA data window */
#define FBR_FUNC_CSA_DATA_OFFSET(fbr)  ((fbr) + 0x0f)
/* Function Block Size Control */
#define FBR_FUNC_BLK_SIZE_LOW_OFFSET(fbr)  ((fbr) + 0x10)
#define FBR_FUNC_BLK_SIZE_HI_OFFSET(fbr)   ((fbr) + 0x11)
#define SDIO_CIS_AREA_BEGIN   0x00001000
#define SDIO_CIS_AREA_END     0x00017fff
/* Tuple definitions */
#define CISTPL_NULL         0x00
#define CISTPL_CHECKSUM     0x10
#define CISTPL_VERS_1       0x15
#define CISTPL_ALTSTR       0x16
#define CISTPL_MANFID       0x20
#define CISTPL_FUNCID       0x21
#define CISTPL_FUNCE        0x22
#define CISTPL_VENDOR       0x91
#define CISTPL_END          0xff
#define CISTPL_LINK_END     0xff


/* these structures must be packed */

/* Manufacturer ID tuple */
struct SDIO_MANFID_TPL {
    UINT16  ManufacturerCode;   /* jedec code */
    UINT16  ManufacturerInfo;   /* manufacturer specific code */
}CT_PACK_STRUCT;

/* Function ID Tuple */
struct SDIO_FUNC_ID_TPL {
    UINT8  DeviceCode;  /* device code */
    UINT8  InitMask;    /* system initialization mask (not used) */
}CT_PACK_STRUCT;

    /* Extended Function Tuple (Common) */
struct SDIO_FUNC_EXT_COMMON_TPL {
    UINT8   Type;                               /* type */
    UINT16  Func0_MaxBlockSize;                 /* max function 0 block transfer size */
    UINT8   MaxTransSpeed;                      /* max transfer speed (encoded) */
#define TRANSFER_UNIT_MULTIPIER_MASK  0x07
#define TIME_VALUE_MASK               0x78
#define TIME_VALUE_SHIFT              3
}CT_PACK_STRUCT;

/* Extended Function Tuple (Per Function) */
struct SDIO_FUNC_EXT_FUNCTION_TPL {
    UINT8   Type;                               /* type */
#define SDIO_FUNC_INFO_WAKEUP_SUPPORT 0x01
    UINT8   FunctionInfo;                       /* function info */
    UINT8   SDIORev;                            /* revision */
    UINT32  CardPSN;                            /* product serial number */
    UINT32  CSASize;                            /* CSA size */
    UINT8   CSAProperties;                      /* CSA properties */
    UINT16  MaxBlockSize;                       /* max block size for block transfers */
    UINT32  FunctionOCR;                        /* optimal function OCR */
    UINT8   OpMinPwr;                           /* operational min power */
    UINT8   OpAvgPwr;                           /* operational average power */
    UINT8   OpMaxPwr;                           /* operation maximum power */
    UINT8   SbMinPwr;                           /* standby minimum power */
    UINT8   SbAvgPwr;                           /* standby average power */
    UINT8   SbMaxPwr;                           /* standby maximum power */
    UINT16  MinBandWidth;                       /* minimum bus bandwidth */
    UINT16  OptBandWidth;                       /* optimalbus bandwitdh */
}CT_PACK_STRUCT;

struct SDIO_FUNC_EXT_FUNCTION_TPL_1_1 {
    struct SDIO_FUNC_EXT_FUNCTION_TPL CommonInfo;  /* from 1.0*/
    UINT16  EnableTimeOut;                  /* timeout for enable */
    UINT16  OperPwrMaxPwr;
    UINT16  OperPwrAvgPwr;
    UINT16  HiPwrMaxPwr;
    UINT16  HiPwrAvgPwr;
    UINT16  LowPwrMaxPwr;
    UINT16  LowPwrAvgPwr;
}CT_PACK_STRUCT;

static INLINE SDIO_STATUS ConvertCMD52ResponseToSDIOStatus(UINT8 CMD52ResponseFlags) {
    if (!(CMD52ResponseFlags & SD_R5_ERRORS)) {
        return SDIO_STATUS_SUCCESS;
    }
    if (CMD52ResponseFlags & SD_R5_ILLEGAL_CMD) {
        return SDIO_STATUS_DATA_STATE_INVALID;
    } else if (CMD52ResponseFlags & SD_R5_INVALID_FUNC) {
        return SDIO_STATUS_INVALID_FUNC;
    } else if (CMD52ResponseFlags & SD_R5_ARG_RANGE_ERR) {
        return SDIO_STATUS_FUNC_ARG_ERROR;
    } else {
        return SDIO_STATUS_DATA_ERROR_UNKNOWN;
    }
}

/* CMD6 mode switch definitions */

#define SD_SWITCH_FUNC_CHECK    0
#define SD_SWITCH_FUNC_SET      ((UINT32)(1 << 31))
#define SD_FUNC_NO_SELECT_MASK  0x00FFFFFF
#define SD_SWITCH_GRP_1         0
#define SD_SWITCH_GRP_2         1
#define SD_SWITCH_GRP_3         2
#define SD_SWITCH_GRP_4         3
#define SD_SWITCH_GRP_5         4
#define SD_SWITCH_GRP_6         5

#define SD_SWITCH_HIGH_SPEED_GROUP     SD_SWITCH_GRP_1
#define SD_SWITCH_HIGH_SPEED_FUNC_NO   1

#define SD_SWITCH_MAKE_SHIFT(grp) ((grp) * 4)

#define SD_SWITCH_MAKE_GRP_PATTERN(FuncGrp,FuncNo) \
     ((SD_FUNC_NO_SELECT_MASK & (~(0xF << SD_SWITCH_MAKE_SHIFT(FuncGrp)))) |  \
        (((FuncNo) & 0xF) << SD_SWITCH_MAKE_SHIFT(FuncGrp)))                 \

#define SD_SWITCH_FUNC_ARG_GROUP_CHECK(FuncGrp,FuncNo) \
    (SD_SWITCH_FUNC_CHECK | SD_SWITCH_MAKE_GRP_PATTERN(FuncGrp,FuncNo))

#define SD_SWITCH_FUNC_ARG_GROUP_SET(FuncGrp,FuncNo)   \
    (SD_SWITCH_FUNC_SET | SD_SWITCH_MAKE_GRP_PATTERN(FuncGrp,FuncNo))

#define SD_SWITCH_FUNC_STATUS_BLOCK_BYTES 64

#define SD_SWITCH_FUNC_STATUS_GET_GRP_BIT_MASK(pBuffer,FuncGrp) \
    (USHORT)((pBuffer)[50 + ((FuncGrp)*2)] | ((pBuffer)[51 + ((FuncGrp)*2)] << 8))

#define SD_SWITCH_FUNC_STATUS_GET_MAX_CURRENT(pBuffer) \
     (USHORT)((pBuffer)[62] | ((pBuffer)[63] << 8))

static INLINE UINT8 SDSwitchGetSwitchResult(PUINT8 pBuffer, UINT8 FuncGrp)
{
    switch (FuncGrp) {
        case 0:
            return (pBuffer[47] & 0xF);
        case 1:
            return (pBuffer[47] >> 4);
        case 2:
            return (pBuffer[48] & 0xF);
        case 3:
            return (pBuffer[48] >> 4);
        case 4:
            return (pBuffer[49] & 0xF);
        case 5:
            return (pBuffer[49] >> 4);
        default:
            return 0xF;
    }
}

#endif